ZOJ 3659 Conquer a New Region(并查集)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4882

题意:给出一棵树,边有权值。两个节点i和j之间的距离D(i,j)定义为i和j之间的路径上最小的权值。求一个点使得该点到其他点的D值和最大?

思路:并查集:将权值按照降序插入并查集。。。一开始我以为是树形DP呢,搞了半天。。

 

#include <stdio.h>

#include <string.h>

#include <algorithm>

#define i64 long long

using namespace std;



struct node

{

    int size,p;

    i64 sum;

};



struct Node

{

    int u,v;

    i64 c;

};



Node b[200005];

node a[200005];

int n;



int cmp(Node a,Node b)

{

    return a.c>b.c;

}



int get(int u)

{

    if(a[u].p!=u) a[u].p=get(a[u].p);

    return a[u].p;

}



void deal()

{

    int i,u,v,ru,rv;

    i64 c,x,y;

    for(i=1;i<=n-1;i++)

    {

        u=b[i].u;

        v=b[i].v;

        c=b[i].c;

        ru=get(u);

        rv=get(v);

        x=a[ru].sum+c*a[rv].size;

        y=a[rv].sum+c*a[ru].size;

        if(x<y)

        {

            a[ru].p=rv;

            a[rv].size+=a[ru].size;

            a[rv].sum=y;

        }

        else

        {

            a[rv].p=ru;

            a[ru].size+=a[rv].size;

            a[ru].sum=x;

        }

    }

    printf("%lld\n",a[get(1)].sum);

}



int main()

{

    while(scanf("%d",&n)!=-1)

    {

        int i;

        for(i=1;i<n;i++) scanf("%d%d%lld",&b[i].u,&b[i].v,&b[i].c);

        sort(b+1,b+n,cmp);

        for(i=1;i<=n;i++)

        {

            a[i].size=1;

            a[i].sum=0;

            a[i].p=i;

        }

        deal();

    }

    return 0;

}

 

  

 

你可能感兴趣的:(new)