HDU 4424Conquer a New Region(并查集)

题意:

给出一个树形图和边权值,边权值是容量,问把某个点作为首都,向其他n-1个点运输货物,货物容量不超过路径上的边权值;问可以输出的最大货物是多少?


思路:

因为限制条件是路径上的最小值,那么我们按价值排序,从大到小排,就可以避免这个问题了,然后利用并查集来完成,对于两个集合,左集合的价值总和为A,右集合的价值总和为B,现在有一条路径连接这两个集合,那么我们考虑的是将A合并到B还是将B合并到A,我们可以这么比较,连接这两个集合的路径肯定是目前最小的价值,如果A集合元素个数为Ai,那么将A合并到B则B需要加A*Ai,反过来A则加B*Bi,比较哪个大就行了,因为它们一定是合并成一块了,价值大的留下


#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define N 200005
struct Edge
{
    int u, v;
    LL w;
    bool operator < (const Edge &other) const
    {
        return w>other.w;
    }
}edge[N];
int fa[N];
LL sum[N], num[N];
int getf(int x)
{
    return fa[x]==x?x:fa[x]=getf(fa[x]);
}
LL solve(int n)
{
    for(int i=0; i<n-1; i++)
    {
        int u=getf(edge[i].u);
        int v=getf(edge[i].v);
        if(sum[u]+num[v]*edge[i].w>=sum[v]+num[u]*edge[i].w)
        {
            fa[v]=u;sum[u]+=num[v]*edge[i].w;
            num[u]+=num[v];
        }
        else
        {
            fa[u]=v;sum[v]+=num[u]*edge[i].w;
            num[v]+=num[u];
        }
    }
    return sum[getf(1)];
}
int main()
{
    int n;
    while(scanf("%d", &n)!=EOF)
    {
        for(int i=0; i<n-1; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            edge[i].u=u;edge[i].v=v;edge[i].w=w;
        }
        sort(edge, edge+n-1);
        for(int i=1; i<=n; i++)
        {
            fa[i]=i;sum[i]=0;num[i]=1;
        }
        LL ans=solve(n);
        printf("%I64d\n", ans);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值