1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<algorithm> 7 #include<iomanip> 8 using namespace std; 9 namespace Moxing { 10 const int N=200005; 11 int n,t,last[N],cnt,root,deg[N],d[N],f[N];bool vis[N]; 12 struct node{ 13 int to,dis,nxt; 14 }edge[N<<1]; 15 void first(){ 16 root=1,cnt=0; 17 memset(edge,0,sizeof(edge)); 18 fill(deg+1,deg+1+n,0); 19 fill(d+1,d+1+n,0); 20 fill(f+1,f+1+n,0); 21 fill(last+1,last+1+n,0); 22 fill(vis+1,vis+1+n,0); 23 } 24 void add(int from,int to,int dis){ 25 edge[++cnt].to=to,edge[cnt].dis=dis,edge[cnt].nxt=last[from],last[from]=cnt; 26 } 27 void dp(int x){ 28 vis[x]=1,d[x]=0; 29 for(int i=last[x];i;i=edge[i].nxt){ 30 int y=edge[i].to; 31 if(vis[y]) continue ; 32 dp(y); 33 if(deg[y]==1) d[x]+=edge[i].dis; 34 else d[x]+=min(d[y],edge[i].dis); 35 } 36 } 37 void dfs(int x){ 38 vis[x]=1; 39 for(int i=last[x];i;i=edge[i].nxt){ 40 int y=edge[i].to; 41 if(vis[y]) continue ; 42 if(deg[x]==1) f[y]=d[y]+edge[i].dis; 43 else f[y]=d[y]+min(f[x]-min(d[y],edge[i].dis),edge[i].dis); 44 dfs(y); 45 } 46 } 47 struct main { 48 main(){ 49 scanf("%d",&t); 50 while(t--){ 51 scanf("%d",&n); 52 first(); 53 for(int i=1;i<=n-1;i++){ 54 int x,y,z; 55 scanf("%d%d%d",&x,&y,&z); 56 add(x,y,z),add(y,x,z); 57 deg[x]++;deg[y]++; 58 } 59 dp(root); 60 fill(vis+1,vis+1+n,0); 61 f[root]=d[root]; 62 dfs(root); 63 int ans=0; 64 for(int i=1;i<=n;i++){ 65 ans=max(ans,f[i]); 66 } 67 printf("%d\n",ans); 68 } 69 exit(0); 70 } 71 72 } UniversalLove; 73 } 74 int main() { 75 Moxing::main(); 76 }
设d[x]表示在以x为根的子树中,把x作为原点,从x出发流向子树的最大流量
d[x]=sigma{
min(d[y],edge[i].dis) (deg[y]>1)
edge[i].dis (dge[y]==1)
}
设f[x]表示把x作为原点,从x出发流向整个水系的最大流量
f[x]={
d[x] (x==root)
d[y]+min(f[x]-min(d[y],edge[i].dis),edge[i].dis) (deg[x]>1)
edge[i].dis (deg[x]=1)
}
poj3585Accumulation Degree-二次扫描与换根法
原文:https://www.cnblogs.com/Moxingtianxia/p/11285164.html