poj3585Accumulation Degree-二次扫描与换根法

 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 }
View Code

设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)

  }

猜你喜欢

转载自www.cnblogs.com/Moxingtianxia/p/11285164.html