hdu4750 Count The Pairs(并查集+二分+最小生成树思想)

hdu4750

题目

给你一个n个点,m条边的图,对于任意两点(s,t),他们的f值是他们所有路径中每条路径中的最大边的最小值,给定询问t,求f值大于等于t的点的对数。

思路

每次加入一条当前最短边,连接起两个联通块,那么这条变相当与两个联通块两两点之间的最长边而且是当前情况最短,点对数是两个联通块点数的乘积,我们按顺序记下,得到相应的询问结果即可。
(思考还是一点点来,一条条边,一个个点这种,总是一大块的考虑,一团浆糊)

代码

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

const int maxn=10010;
const int maxx=500100;

typedef long long ll;

int f[maxn],n,m,q,tot;
int son[maxn],len[maxn];
ll sum[maxn];

int Find(int x)
{
    if (x!=f[x])
        f[x]=Find(f[x]);
    return(f[x]);
}

struct node
{
    int a,b,c;
    bool operator <(const node p)const
    {
        return c<p.c;
    }
} e[maxx];

int main ()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        for(int i=0; i<n; i++)
        {
            f[i]=i;
            son[i]=1;
        }
        for(int i=0; i<m; i++)
        {
            scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].c);
        }
        sort(e,e+m);
        tot=2;
        len[0]=sum[0]=len[1]=sum[1]=0;
        for(int i=0; i<m; i++)
        {
            int x=Find(e[i].a);
            int y=Find(e[i].b);
            if(x==y) continue;
            len[tot]=e[i].c;
            sum[tot++]=(ll)son[x]*son[y];
            f[x]=y;
            son[y]+=son[x];
        }
        for(int i=1; i<tot; i++)
            sum[i]+=sum[i-1];
        scanf("%d",&q);
        for(int i=0; i<q; i++)
        {
            int t;
            scanf("%d",&t);
            int id=lower_bound(len,len+tot,t)-len-1;
            printf("%I64d\n",(sum[tot-1]-sum[id])*2);
        }

    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值