除了源点之外,树中所有度数为1
的节点都是入海口,可以吸收无限多的水,我们称之为汇点。
也就是说,水系中的水从源点出发,沿着每条河道,最终流向各个汇点。
问最大流量
f[ x] =min( f[y] ,z)
换根,考虑 g[x] 流向所有(包括x往上) 时的最大流量
g[y]=f[y]+ min( z, g[x]- min(z, f[y]) )
#include <iostream> #include <cstring> using namespace std; const int N=2e5+30,M=2*N; int all,hd[N],w[M],nxt[M],go[M],n; int g[N],f[N],in[N]; void add(int x,int y,int z){ go[++all]=y,nxt[all]=hd[x],hd[x]=all; w[all]=z; } void dp(int x,int fa){ int y,z,i; f[x]=0; for(i=hd[x];i;i=nxt[i]){ y=go[i],z=w[i]; if(y==fa) continue; dp(y,x); if(in[y]<=1) f[x]+=z; else f[x]+=min(z,f[y]); } } void dfs(int x,int fa){ int y,z,i; for(i=hd[x];i;i=nxt[i]){ y=go[i],z=w[i]; if(y==fa) continue; if(in[x]==1) g[y]=z+f[y]; else g[y]=f[y]+min(g[x]-min(f[y],z),z); dfs(y,x); } } signed main(){ int i,tes; cin>>tes; while(tes--){ cin>>n; int x,y,z; for(i=1;i<=n;i++) f[i]=g[i]=in[i]=hd[i]=0; all=0; for(i=1;i<n;i++) cin>>x>>y>>z,add(x,y,z),add(y,x,z), in[y]++,in[x]++; dp(1,-1); g[1]=f[1]; dfs(1,-1); int ans=0; for(i=1;i<=n;i++) ans=max(ans,g[i]); cout<<ans<<endl; } }
标签:min,int,积蓄,add,hd,go,287,dp,acwing From: https://www.cnblogs.com/towboa/p/17158293.html