bzoj 1060 时态同步

题目大意:

一棵树,给定根节点,可以给某些边加上一些权值,每加一,答案加一

求最小答案使根节点到每个叶子节点路径上的权值和相

思路:

树形dp

对于每个节点,dp表示到该节点的所有叶子节点 满足题目的最小答案

转移可以根据它所有子节点转移

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<set>
 8 #include<map>
 9 #include<vector>
10 #include<stack>
11 #include<queue>
12 #define ll long long
13 #define inf 2147383611
14 #define MAXN 500100
15 using namespace std;
16 inline ll read()
17 {
18     ll x=0,f=1;
19     char ch;ch=getchar();
20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
21     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
22     return x*f;
23 }
24 int n,rt,fa[MAXN];
25 int next[MAXN*2],to[MAXN*2],first[MAXN],val[2*MAXN],cnt;
26 ll ans,dp[MAXN];
27 void add(int u,int v,int d) {next[++cnt]=first[u],first[u]=cnt,to[cnt]=v,val[cnt]=d;}
28 void dfs(int x,int fa)
29 {
30     for(int i=first[x];i;i=next[i])
31     {
32         if(to[i]==fa) continue;
33         dfs(to[i],x);
34         dp[x]=max(dp[x],dp[to[i]]+val[i]);
35     }
36     for(int i=first[x];i;i=next[i]) if(to[i]!=fa) ans+=dp[x]-dp[to[i]]-val[i];
37 }
38 int main()
39 {
40     n=read(),rt=read();
41     int a,b,c;
42     for(int i=1;i<n;i++) {a=read(),b=read(),c=read();add(a,b,c);add(b,a,c);}
43     dfs(rt,0);
44     printf("%lld",ans);
45 }
View Code
 
posted @ 2017-10-24 21:01  jack_yyc  阅读(155)  评论(0编辑  收藏  举报