题意
给定一棵个节点的无向带权树,要你找出一个节点作为根,向叶子节点流水,使流水量最大。
思路
换根DP
这种题往往都是先从某个点出发,求出以这个节点为根的答案,并记录与答案相关的数据到数组中。
然后从节点出发,记录换根的答案,其中所有根的最大值就为所求值。
难点在于该如何去找寻其中的递推关系式。
数组表示该点的最大水流量,数组表示一该点为根的答案,为度数。
当节点由转移到时,分为两个部分,其中一个部分是,另一个部分为与节点相连的部分。
注意:要对fa节点是否为根节点进行讨论。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>P; const double eps = 1e-8; const int NINF = 0xc0c0c0c0; const int INF = 0x3f3f3f3f; const ll mod = 1e9 + 7; const ll maxn = 1e6 + 5; const int N = 2e5 + 5; int n; ll d[N],f[N],ans; vector<pair<int,int> > G[N]; void dp(int x,int fa){ for(auto c:G[x]){ ll u=c.first,v=c.second; if(u==fa) continue; dp(u,x); if(d[u]!=0) d[x]+=min(d[u],v); else d[x]+=v; } } void dfs(int x,int fa,ll v){ if(fa!=-1){ f[x]=d[x]; if(G[fa].size()!=1) f[x]+=min(f[fa]-min(d[x],v), v); else f[x]+=v; } for(auto c:G[x]){ ll u=c.first,p=c.second; if(u==fa) continue; dfs(u,x,p); } } void solve(){ cin>>n; for(int i=1;i<=n;i++) G[i].clear(),d[i]=0,f[i]=0; for(int i=1;i<n;i++){ int u,v,w;cin>>u>>v>>w; G[u].push_back({v,w}); G[v].push_back({u,w}); } dp(1,-1); f[1]=d[1]; dfs(1,-1,G[1][0].second); cout<<*max_element(f+1,f+1+n)<<'\n'; } int main(){ ios::sync_with_stdio(false); cin.tie(0); int T;cin>>T; while(T--){ solve(); } return 0; }