ZOJ 3659 Conquer a New Region(12年长春site E)

ACM_数据结构 专栏收录该内容
81 篇文章 0 订阅

转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526       by---cxlove 

题目:给出一棵树,找出一个点,求出所有点到这个点的权值和最大,权值为路径上所有边权的最小值。

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3659 

比赛的时候卡了,一直往DP上想。

结果并查集搞定。

按边排序,从大到小插入,每条边将两个集合连起来,而新加的边是两个集合所有边最小的,那么两个集合中的点交叉的通路最小的边就是新加的,那只要枚举两个集合,a,b是a并入b更优还是b并入a更优就行了。集合内部点已经计算出,相互的只要知道集合中元素的个数就好了。

所以并查集只需要维护一个集合的元素个数,一个集合的总权值

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 200005
#define MOD 1000000007
#define LL long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
struct Node
{
    int u,v,w;
    bool operator< (const Node n1) const
    {
        return w>n1.w;
    }
}edge[N];
int cnt[N],pre[N];
LL sum[N];
int find(int a)
{
    return pre[a]=(a==pre[a]?a:find(pre[a]));
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n-1;i++)
        {
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        sort(edge,edge+n-1);
        for(int i=1;i<=n;i++)
        {
            sum[i]=0;
            pre[i]=i;
            cnt[i]=1;
        }
        LL ans=0;
        for(int i=0;i<n-1;i++)
        {
            int ra=find(edge[i].u);
            int rb=find(edge[i].v);
            LL atob=(LL)cnt[ra]*edge[i].w+sum[rb];
            LL btoa=(LL)cnt[rb]*edge[i].w+sum[ra];
            if(atob>btoa)
            {
                pre[ra]=rb;
                cnt[rb]+=cnt[ra];
                sum[rb]=atob;
            }
            else
            {
                pre[rb]=ra;
                cnt[ra]+=cnt[rb];
                sum[ra]=btoa;
            }
            ans=max(ans,max(atob,btoa));
        }
        printf("%lld\n",ans);
    }
    return 0;
}


  • 4
    点赞
  • 4
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

ACM_cxlove

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值