hdu 5834

题意:有n个点的树,边上有值w,每次经过这条边,都要花费w,每个点有一个值,到达过该点可以获得该值,每个点只能获得一次,求从每个点出发,所能获得的最大值分析:选择一个点作为根,那么每个考虑从每个点走向子树和走向父亲,回来和不回来的最大值,答案就说max(儿子回来+父亲不回来,父亲回来+儿子不回来),走向儿子的好求,只是走向父亲的难求一些,但是加上一点,就是考虑父亲是不是有必要向当前的儿子走和不回来的儿子是不是该点就好求了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+5;
 4 //Ê÷
 5 int head[maxn],to[maxn*2],nxt[maxn*2],tot,cost[maxn*2];
 6 void addedge(int u,int v,int w){
 7     ++tot;
 8     nxt[tot]=head[u];
 9     to[tot]=v;
10     cost[tot]=w;
11     head[u]=tot;
12 }
13 
14 int val[maxn],dp[maxn][2],fa[maxn][2],p[maxn],fp[maxn];
15 int n,t;
16 
17 void dfs1(int u,int f){
18     dp[u][0]=dp[u][1]=val[u];p[u]=f;fp[u]=u;
19     for(int i=head[u];~i;i=nxt[i]){
20         int v=to[i],w=cost[i];if(v==f)continue;
21         dfs1(v,u);
22         dp[u][1]+=max(0,dp[v][0]-2*w);
23         if(dp[u][1]<dp[u][0]+dp[v][1]-w)
24             fp[u]=v,dp[u][1]=dp[u][0]+dp[v][1]-w;
25         dp[u][0]+=max(0,dp[v][0]-2*w);
26     }
27 }
28 
29 void dfs2(int u,int f,int d){
30     fa[u][0]=fa[u][1]=0;
31     if(dp[u][0]<=2*d){
32         fa[u][0]=max(0,fa[f][0]+dp[f][0]-2*d);
33         fa[u][1]=max(0,fa[f][1]+dp[f][0]-d);
34     }
35     else{
36         fa[u][0]=max(0,fa[f][0]+dp[f][0]-dp[u][0]);
37         fa[u][1]=max(0,fa[f][1]+dp[f][0]-dp[u][0]+d);
38     }
39     if(fp[f]==u){
40         int mx1=val[f],mx2=val[f];
41         for(int i=head[f];~i;i=nxt[i]){
42             int v=to[i],w=cost[i];
43             if(v==p[f]||v==u)continue;
44             mx1=max(mx1,mx1+dp[v][0]-2*w);
45             mx1=max(mx1,mx2+dp[v][1]-w);
46             mx2+=max(0,dp[v][0]-2*w);
47         }
48         fa[u][1]=max(fa[u][1],mx1+fa[f][0]-d);
49     }
50     else{
51         if(dp[u][0]>=2*d)
52             fa[u][1]=max(fa[u][1],fa[f][0]+dp[f][1]-dp[u][0]+d);
53         else
54             fa[u][1]=max(fa[u][1],fa[f][0]+dp[f][1]-d);
55     }
56     for(int i=head[u];~i;i=nxt[i])
57         if(to[i]!=f)dfs2(to[i],u,cost[i]);
58 }
59 
60 void init(){
61     tot=0;
62     memset(head,-1,sizeof(head));
63 }
64 
65 int main(){
66     scanf("%d",&t);
67     int cas=1;
68     while(t--){
69         scanf("%d",&n);
70         for(int i=1;i<=n;i++)scanf("%d",val+i);
71         init();
72         for(int i=1;i<n;i++){
73             int u,v,w;scanf("%d%d%d",&u,&v,&w);
74             addedge(u,v,w);addedge(v,u,w);
75         }
76         dfs1(1,0);
77         dfs2(1,0,0);
78         printf("Case #%d:\n",cas++);
79         for(int i=1;i<=n;i++)
80             printf("%d\n",max(dp[i][0]+fa[i][1],dp[i][1]+fa[i][0]));
81     }
82     return 0;
83 }
View Code

 

posted @ 2016-10-28 12:33  N维解析几何  阅读(345)  评论(0编辑  收藏  举报