标签:des style blog io color ar os sp for
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
标签:des style blog io color ar os sp for
原文地址:http://blog.csdn.net/u011345136/article/details/40950461