HDU 4118--Holiday's Accommodation(树形dp)

来源:互联网 发布:linux 挂载大硬盘 编辑:程序博客网 时间:2024/06/11 15:06

来源:http://acm.hdu.edu.cn/showproblem.php?pid=4118

题意:给n个点,每个点有一个人,有n-1条有权值的边,求所有人不在原来位置所移动的距离的和最大值。

思路:对于每一个边,都可以把这个变量偷的点交换,这样这些点都要走这个边,就是这个边要走2*min(左端的点数,右端的点数)。但是会爆栈,可以人工开栈,也可用非递归的方法写dfs,同样可以过。

#pragma comment(linker, "/STACK:10240000000000,10240000000000")#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#define MAXN 101005#define MAXM 400005#define INF 1000000000using namespace std;struct EDGE{    int v, next;    long long w;}edge[MAXM];int head[MAXN], e;int n;int num[MAXN];long long ans;void init(){    ans = 0;    memset(head, -1, sizeof(head));    e = 0;    memset(num, 0, sizeof(num));}void add(int u, int v, long long w){    edge[e].v = v;    edge[e].w = w;    edge[e].next = head[u];    head[u] = e++;}void dfs(int u, int fa){    num[u] = 1;    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].v;        if(v != fa)        {            dfs(v, u);            num[u] += num[v];            long long tmp = min(num[v], n - num[v]);            ans += tmp * edge[i].w * 2LL;        }    }}int main(){    int T, cas = 0, x, y, z;    scanf("%d", &T);    while(T--)    {        scanf("%d", &n);        init();        for(int i = 1; i < n; i++)        {            scanf("%d%d%d", &x, &y, &z);            add(x, y, z);            add(y, x, z);        }        dfs(1, 0);        printf("Case #%d: %I64d\n", ++cas, ans);    }    return 0;}