POJ3585 Accumulation Degree【换根dp】
题意
给出一棵树,树上的边都有容量,在树上任意选一个点作为根,使得往外流(到叶节点,叶节点可以接受无限多的流量)的流量最大。
分析
首先,还是从1号点工具人开始$dfs$,可以求出$dp[i]$为点$i$向它的子树中可以获得的最大流量。
接下来考虑换根,设$f[i]$是以$i$为根节点的答案(向它的所有根节点能够发射的最大流量之和)
考虑把根从$u$换到$v$,$v$自己子树内的答案$dp[v]$肯定是在$f[v]$之内的
经过了$u-v$这条边的答案就是$min(f[u]-min(w,dp[v]),w)$
加起来就是$f[v]=dp[v]+min(f[u]-min(w,dp[v]),w)$
理解一下:$f[u]-min(w,dp[v])$是减去红圈里的贡献,也就是$u$不往$v$里面流也产生的答案。要取$min(w,dp[v])$是因为$u$真正能流进$v$子树里的流量还要受到$w$的限制
相同地,把$v$当做根之后往$u$方向流的流量也会受到$w$的限制,所以也要取$min$。
另外,特别地,还有这种情况:
(这种情况真的好难想到的说)
这种情况的话,答案就直接是$f[v]=dp[v]+w$
然而用上面的式子的话,$f[u]-min(w,dp[v])=0$,变成$f[v]=dp[v]$,是不成立的。所以需要特判一下。
然后就做
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<cstring> 5 using namespace std; 6 #define N 200005 7 #define ll long long 8 #define INF 0x3f3f3f3f 9 int n,ans; 10 int dp[N],f[N]; 11 vector<pair<int,int> >G[N]; 12 int rd() 13 { 14 int f=1,x=0;char c=getchar(); 15 while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} 16 while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();} 17 return f*x; 18 } 19 void dfs(int u,int p) 20 { 21 int tmp=0; 22 for(int i=0;i<G[u].size();i++) 23 { 24 int v=G[u][i].first,w=G[u][i].second; 25 if(v==p) continue; 26 dfs(v,u); 27 tmp+=min(dp[v],w); 28 } 29 if(tmp) dp[u]=tmp; 30 return ; 31 } 32 void dfs2(int u,int p) 33 { 34 ans=max(ans,f[u]); 35 for(int i=0;i<G[u].size();i++) 36 { 37 int v=G[u][i].first,w=G[u][i].second; 38 if(v==p) continue; 39 if(G[u].size()==1) 40 { 41 f[v]=dp[v]+w; 42 dfs2(v,u); 43 } 44 else 45 { 46 f[v]=dp[v]+min(w,f[u]-min(w,dp[v])); 47 dfs2(v,u); 48 } 49 } 50 } 51 int main() 52 { 53 int T=rd(); 54 while(T--) 55 { 56 n=rd(); 57 if(n==0) 58 {//特判 59 puts("0"); 60 continue; 61 } 62 ans=0; 63 memset(dp,INF,sizeof(dp)); 64 for(int i=1;i<=n;i++) 65 G[i].clear(); 66 for(int i=1;i<n;i++) 67 { 68 int u=rd(),v=rd(),w=rd(); 69 G[u].push_back(make_pair(v,w)); 70 G[v].push_back(make_pair(u,w)); 71 } 72 dfs(1,-1); 73 for(int i=1;i<=n;i++) 74 if(dp[i]==INF) 75 dp[i]=0;//叶节点 76 f[1]=dp[1]; 77 dfs2(1,-1); 78 printf("%d\n",ans); 79 } 80 }
完啦。
转载请注明出处,有疑问欢迎探讨
博主邮箱 2775182058@qq.com