luogu 1131 [ZJOI2007]时态同步

分析

一句话题意,各个叶节点到根的距离与其最长距离的差的和

一个儿子至少代表一个叶节点

求的话,在每个节点时将各个儿子(代表一组叶节点)的距离调成一样

 再将差加起来就好

代码

 1 /***************************** 
 2 User:Mandy.H.Y
 3 Language:c++
 4 Problem:luogu1131
 5 Algorithm:
 6 *****************************/
 7 
 8 #include<bits/stdc++.h>
 9 
10 using namespace std;
11 
12 const int maxn = 5e5 + 5;
13 
14 int n,s;
15 long long sum;
16 int size,first[maxn];
17 long long dp[maxn],dis[maxn];
18 //dis是i的子树中的离i最远的叶子到i的距离 
19 struct Edge{
20     int v,w,nt;
21 }edge[maxn << 1];
22 
23 template<class T>inline void read(T &x){
24     x = 0;char ch = getchar();bool flag = 0;
25     while(!isdigit(ch)) flag |= ch == '-',ch = getchar();
26     while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar();
27     if(flag) x = -x;
28 }
29 
30 void file(){
31     freopen("1311.in","r",stdin);
32     freopen("1311.out","w",stdout);
33 }
34 
35 void eadd(int u,int v,int w){
36     edge[++size].v = v;
37     edge[size].w = w;
38     edge[size].nt = first[u];
39     first[u] = size;
40 }
41 
42 void readdata(){
43     read(n);read(s);
44     for(int i = 1;i < n; ++ i){
45         int u,v,w;
46         read(u);read(v);read(w);
47         eadd(u,v,w);eadd(v,u,w);
48     }
49 }
50 
51 void dfs(int u,int fa){
52     long long mdis = 0;
53     for(int i = first[u];i;i = edge[i].nt){
54         int v = edge[i].v;
55         int w = edge[i].w;
56         if(v == fa) continue;
57         dfs(v,u);
58         if(mdis<dis[v]+w)
59             mdis = dis[v]+w;
60     }
61     dis[u] = mdis;
62     for(int i = first[u];i;i = edge[i].nt){
63         int v = edge[i].v;
64         int w = edge[i].w;
65         if(v == fa) continue;
66         sum += mdis - (dis[v]+w); 
67     }
68 }
69 
70 void work(){
71     dfs(s,0);
72     printf("%lld",sum);
73 }
74 
75 int main(){
76 //    file();
77     readdata();
78     work();
79     return 0;
80 }
View Code
原文地址:https://www.cnblogs.com/Mandy-H-Y/p/11510074.html