树上的运算
题意: 给出一棵树, 树上边上有权值, 现在每个点都要移动到另一个点。现在求他们移动的最大权值。
思路:这道题没有推出来, 后来看了别人的报告。 说每条边都按可以经过的最大次数计算就行。即求出该条边左右点个数的较小的那个值乘以2就行,不明白为什么。还有就是会RE, 起始点可以选择n/2
AC 代码:
View Code
#pragma comment(linker, "/STACK:10240000000,10240000000") #include <cstdio> #include <cstring> #include <string> #include <iostream> #include <cmath> using namespace std; typedef long long LL; const int N = 201000; struct EDGE { int u, v, w, next; }edge[N]; int d[N], n, num, head[N]; LL ans; void add(int u, int v, int w) { edge[num].u = u; edge[num].v = v; edge[num].w = w; edge[num].next = head[u]; head[u] = num++; } void init() { scanf("%d", &n); num = 0; memset(head, -1, sizeof(head)); int u, v, w; for(int i=1; i<n; i++) { scanf("%d%d%d", &u, &v, &w); add(u, v, w); add(v, u, w); } } void dfs(int u, int pre) { int v; d[u] = 1; for(int i=head[u]; i!=-1; i=edge[i].next) { v = edge[i].v; if(v == pre) continue; dfs(v, u); d[u] += d[v]; ans += min(d[v], n-d[v]) * 2*edge[i].w; } } void solve() { ans = 0; dfs(n/2,-1); printf("%lld\n", ans); } int main() { int t; scanf("%d", &t); for(int i=1; i<=t; i++) { init(); printf("Case #%d: ",i); solve(); } return 0; }


浙公网安备 33010602011771号