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 }