[ZJOI2007]时态同步 树形DP
生活随笔
收集整理的這篇文章主要介紹了
[ZJOI2007]时态同步 树形DP
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:給定一棵N個節點的無根樹,每條邊都有一個權值V,選取其中一個點作為關鍵點,你可以任意增加某條邊的權值,求使得從關鍵點出發,到任意一個葉子節點的距離都相同所需要增加的權值和。
?
數據范圍:
對于40%的數據,N ≤ 1000
對于100%的數據,N ≤ 500000,V?≤ 1000000
?-------------------------------------分割線------------------------------------
題解:一道比較顯然的樹形DP,不難想到我們把其他的鏈都向最長鏈看齊。
掃描一遍樹,自底向上處理出當前節點的出邊數量num,以及當前節點到葉節點的距離和sum。
算出最遠的距離激發器的葉子節點距離maxn[x],然后對于其他葉子節點,所需要增加的長度顯然即為 maxn[x] * num - sum。
累加答案即可。
#include<bits/stdc++.h>#define ll long long #define mp make_pair #define rep(i, a, b) for(int i = (a); i <= (b); i++) #define per(i, a, b) for(int i = (a); i >= (b); i--)using namespace std;typedef pair<int, int> pii; typedef double db; const int N = 1e6 + 50; int n, a[N], root; int head[N], cnt = 0; ll maxn[N], f[N]; struct node{ ll to, next, v; } e[N]; inline int read(){int x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar();}while(ch >='0' && ch <='9') { x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}return x*f; } void add(int x, int y, int z){e[++cnt].to = y; e[cnt].v = z;e[cnt].next = head[x]; head[x] = cnt; } void init(){n = read(); root = read();rep(i, 1, n-1) {int xx, yy, zz;xx = read(); yy = read(); zz = read();add(xx, yy, zz);add(yy, xx, zz);} } void dfs(int x, int fa){f[x] = 0, maxn[x] = 0;ll sum = 0, num = 0;for(int i = head[x]; i; i = e[i].next){int y = e[i].to;if(y == fa) continue;dfs(y, x); num ++;f[x] += f[y];maxn[x] = max(maxn[y] + e[i].v, maxn[x]);sum += (ll)maxn[y] + e[i].v; }f[x] += (ll)maxn[x] * num - sum; } void work(){dfs(root, 0);printf("%lld\n", f[root]); } int main(){init();work();return 0; } View Code?
轉載于:https://www.cnblogs.com/smilke/p/11576955.html
總結
以上是生活随笔為你收集整理的[ZJOI2007]时态同步 树形DP的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: srand(设置随机数种子)
- 下一篇: java网页解析包_java 网页解析工