日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[换根] Accumulation Degree

發布時間:2023/12/8 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [换根] Accumulation Degree 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題面

link
??給定一棵樹,每條邊有流量限制,一個結點的流量定義為將該點看為源點,最多能流出多少水(可以從不是自身的葉子結點流出),問這棵樹最大的結點流量是多少?

分析

??求出一個結點的流量,我們可以對這個結點用一遍樹型dp,對于結點 uuu 和 其兒子 vvv, 若 vvv 是葉子結點,那么 dp[u]+=w(u,v)dp[u] += w(u, v)dp[u]+=w(u,v), 否則 dp[u]+=min(dp[v],w(u,v))dp[u] += min(dp[v], w(u, v))dp[u]+=min(dp[v],w(u,v))。對一個結點我們可以用 O(n)O(n)O(n) 時間算出其流量,但是若是用此法算出所有的結點,是O(n2)O(n^2)O(n2) 的復雜度,會超時。
??這時候就要考慮換根的思想:先算出固定某一點為根的答案然后考慮把它的兒子換成根會發生什么樣的變化,如果這個變化是比較好算的,那么我們就可考慮每個點x為根的答案都根據以它父親為根的結果去推。
??若我們算出父親的流量 f[u]f[u]f[u], 對于 兒子的流量 f[v]f[v]f[v], 若 vvv 是葉子結點,那么 f[u]f[u]f[u] 中肯定有 w(u,v)w(u, v)w(u,v) 流向 vvvf[u]?w(u,v)f[u] - w(u, v)f[u]?w(u,v) 流向其他,那么從 vvv 就最多可以流出去 min(f[u]?w,w)min(f[u] - w, w)min(f[u]?w,w); 若 vvv 不是, 那么 f[u]f[u]f[u]min(w,dp[v])min(w, dp[v])min(w,dp[v]) 流向 vvvf[u]?min(w,dp[v])f[u] - min(w, dp[v])f[u]?min(w,dp[v]) 流向其他,那么從 vvv 就最多可以流出去 dp[to]+min(w,f[u]?min(w,dp[v]))dp[to] + min(w, f[u] - min(w, dp[v]))dp[to]+min(w,f[u]?min(w,dp[v]))
??那么我們需要兩遍 dfs, 第一遍算出一個結點的流量,第二遍進行換根。

#include <bits/stdc++.h> #define pb push_backusing namespace std;typedef long long ll; typedef pair<int, int> P; const int maxn = 2e5 + 10; const int INF = 0x3f3f3f3f; const ll mod = 998244353;struct edge {int to, next, w; }e[maxn*2];int head[maxn], num, t, n, deg[maxn], d[maxn], f[maxn];void add_edge(int x, int y, int w) {e[++num].to = y;e[num].w = w;e[num].next = head[x];head[x] = num; }void dfs1(int x, int fa) //求出結點1的流量 {d[x] = 0;for(int i = head[x]; i; i = e[i].next){int to = e[i].to, w = e[i].w;if(to == fa) continue;dfs1(to, x);if(deg[to] == 1) d[x] += w;else d[x] += min(d[to], w);} }void dfs2(int x, int fa) //換根 {for(int i = head[x]; i; i = e[i].next){int to = e[i].to, w = e[i].w;if(to == fa) continue;if(deg[to] == 1) f[to] = min(f[x]- w, w);else f[to] = d[to] + min(f[x] - min(w, d[to]), w);dfs2(to, x);} }int main() {scanf("%d", &t);while(t--){scanf("%d", &n);fill(head + 1, head + 1 + n, 0);fill(deg + 1, deg + 1 + n, 0);num = 0;for(int i = 1; i < n; i++){int x, y, z;scanf("%d %d %d", &x, &y, &z);add_edge(x, y, z); add_edge(y, x, z);deg[x]++; deg[y]++;}dfs1(1, 0);f[1] = d[1];dfs2(1, 0);int ans = 0;for(int i = 1; i <= n; i++) ans = max(ans, f[i]);printf("%d\n", ans);} }

總結

以上是生活随笔為你收集整理的[换根] Accumulation Degree的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。