标签:
2 4 1 2 3 2 3 2 4 3 2 6 1 2 3 2 3 4 2 4 1 4 5 8 5 6 5
Case #1: 18 Case #2: 62
题意:一颗树。相应1-n的结点,如今要求是每一个结点原本的人都走到不一样的结点去,每一个人都有路程,求总的最大路程
思路:对于每条边我们能想到的是:这条边左边的结点都跑到右边去,右边的 结点都跑到左边去。所以每条边。都会被走min{left[num], sum-left[nu,]}*2次,依据这个原则我们进行树形DP。可是这题递归的写法会跪。所以仅仅能手动DFS
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 200010; struct Node { int to, next; int len; } edge[maxn<<1]; int head[maxn], num[maxn], cnt, n; int sta[maxn], vis[maxn]; ll ans; void init() { cnt = 0; memset(head, -1, sizeof(head)); memset(num, 0, sizeof(num)); } void add(int u, int v, int len) { edge[cnt].to = v; edge[cnt].len = len; edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].to = u; edge[cnt].len = len; edge[cnt].next = head[v]; head[v] = cnt++; } void dfs(int u) { memset(vis, 0, sizeof(vis)); int top = 0; sta[top++] = u; vis[u] = 1; while (top > 0) { int flag = 1; int cur = sta[top-1]; for (int i = head[cur]; i != -1; i = edge[i].next) { int v = edge[i].to; if (vis[v]) continue; flag = 0; sta[top++] = v; vis[v] = 1; } if (flag == 0) continue; top--; for (int i = head[cur]; i != -1; i = edge[i].next) { int v = edge[i].to; if (num[v] != 0) { num[cur] += num[v]; ans += (ll) edge[i].len * min(num[v], n - num[v]); } } num[cur]++; } } int main() { int t, cas = 1; int u, v, w; scanf("%d", &t); while (t--) { scanf("%d", &n); init(); ans = 0; for (int i = 1; i < n; i++) { scanf("%d%d%d", &u, &v, &w); add(u, v, w); } dfs(1); printf("Case #%d: %I64d\n", cas++, ans*2); } return 0; }
HDU - 4118 Holiday's Accommodation
标签:
原文地址:http://www.cnblogs.com/mengfanrong/p/5413836.html