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 }
非做顽石不可,哪管他敬仰暗唾