树上的运算

题意: 给出一棵树, 树上边上有权值, 现在每个点都要移动到另一个点。现在求他们移动的最大权值。

 

思路:这道题没有推出来, 后来看了别人的报告。 说每条边都按可以经过的最大次数计算就行。即求出该条边左右点个数的较小的那个值乘以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;
 }

 

 

posted @ 2012-09-29 19:16  Gu Feiyang  阅读(188)  评论(0)    收藏  举报