您的位置:首页 > 大数据 > 人工智能

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

2016-09-15 10:58 423 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: