HDU 4424 Conquer a New Region 并查集

本文介绍了一种求解最大承载量之和的问题,通过将点间的承载量按大小排序并使用并查集来更新各点承载量,最终找到以某点为中心时承载量之和的最大值。

题意:给出n个点和n-1条边,a到b的最大承载量为a和b之间承载量的最小值。以某一点为中心,求承载量之和的最大值。

由于a和b之间的承载量为它们之间承载量的最小值,所以先以两点之间的承载量从大到小排序。每次合并时有A,B两个集合,他们之间的承载量(cost)为当前最小,如果B合并到A,则A的总承载量为A之前的总承载量加上A,B之间的承载量成衣集合B中点的个数,即 cost[A]=cost[A]+num[B]*cost.

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;
const int inf=1000000000;
const int maxn=200005;
int f[maxn];
ll num[maxn],cost[maxn];

struct Branch
{
    int a;
    int b;
    ll cost;
}bra[maxn];
bool cmp(Branch a,Branch b)
{
    return a.cost>b.cost;
}
int Find(int x)
{
    if(x!=f[x])
        f[x]=Find(f[x]);
    return f[x];
}
ll Function(int n)
{
    for(int i=0;i<n-1;i++)
    {
        int a=Find(bra[i].a);
        int b=Find(bra[i].b);
        if(cost[a]+num[b]*bra[i].cost>=cost[b]+num[a]*bra[i].cost)
        {
            f[b]=a;
            cost[a]+=num[b]*bra[i].cost;
            num[a]+=num[b];
        }
        else
        {
            f[a]=b;
            cost[b]+=num[a]*bra[i].cost;
            num[b]+=num[a];
        }
    }
    return cost[Find(1)];
}
int main()
{
    //freopen("in.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<=n;i++)
        {
            f[i]=i;
            num[i]=1;
        }
        memset(cost,0,sizeof(cost));
        for(int i=0;i<n-1;i++)
            scanf("%d%d%I64d",&bra[i].a,&bra[i].b,&bra[i].cost);
        sort(bra,bra+n-1,cmp);
        printf("%I64d\n",Function(n));
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/pach/p/5764112.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值