题意:
给一棵 n 个点的边 + 点权树,求带权重?
思路:
其实这题和之前那个 Sta 有点像,我们同样只需要预处理出一个 f[u] 代表以 u 为集合点的方便程度,那么我们就可以O(1)的转移了
假设 v 是 u 的儿子,f[v] = f[u] - (siz[v] * len) + (n - siz[v] ) * len = f[u] + (n - 2 * siz[v] ) * len
这题有一个坑,就是你的INF得开的特别大,不然你就没有 100 了
#include <iostream> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #define LL long long #define INF 0x3f3f3f3f3f3f3f3f #define ls nod<<1 #define rs (nod<<1)+1 const double eps = 1e-10; const int maxn = 1e5 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; struct edge { int v,nxt,w; }e[maxn << 1]; int head[maxn]; LL siz[maxn],dis[maxn],num[maxn],f[maxn]; int cnt,n; LL ans; inline void add_edge(int u,int v,int w) { e[++cnt].v = v; e[cnt].w = w; e[cnt].nxt = head[u]; head[u] = cnt; } inline void dfs(int u,int f) { siz[u] = num[u]; for (int i = head[u];~i;i = e[i].nxt) { int v = e[i].v,len = e[i].w; if (v == f) continue; dis[v] = dis[u] + len; dfs(v,u); siz[u] += siz[v]; } } inline void func(int x,int fa) { for (int i = head[x];~i;i = e[i].nxt) { int v = e[i].v,len = e[i].w; if (v == fa) continue; f[v] = f[x] - siz[v] * len + (siz[1] - siz[v]) * len; func(v,x); } } int main() { memset(head,-1, sizeof(head)); cnt = 0; ans = INF; cin >> n; for (int i = 1;i <= n;i++) { cin >> num[i]; } for (int i = 1;i < n;i++) { int u,v,w; cin >> u >> v >> w; add_edge(u,v,w); add_edge(v,u,w); } dfs(1,0); for (int i = 1;i <= n;i++) { f[1] += (dis[i]*num[i]); } func(1,0); for (int i = 1;i <= n;i++) { ans = min(ans,f[i]); } cout << ans << endl; return 0; }
原文地址:https://www.cnblogs.com/-Ackerman/p/12339717.html
时间: 2024-11-09 03:01:23