#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=1e4+10;
const int maxm=5e5+10;
struct node{
int a,b,c;
}e[maxm];
int f[maxn],n,m,ans[maxm],g[maxn],q[maxm];
int cmp(node x,node y)
{
return x.c<y.c;
}
void init()
{
int i,j,k;
for(i=0;i<=n;i++){f[i]=i;g[i]=1;}
}
int find(int x)
{
if(f[x]!=x)f[x]=find(f[x]);
return f[x];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j,k,a,b,c,aa,bb,p,t,tt;
init();
for(i=1;i<=m;i++)
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
sort(e,e+m,cmp);
ans[0]=0;
q[m]=2e9;
//ans[i]表示两点价值小于等于e[i].c的点对数。
for(i=1;i<=m;i++)
{
q[i-1]=e[i].c;
aa=find(e[i].a);
bb=find(e[i].b);
if(aa==bb){ans[i]=ans[i-1];}
else
{
ans[i]=ans[i-1]-g[aa]*(g[aa]-1)-g[bb]*(g[bb]-1)+(g[aa]+g[bb]-1)*(g[aa]+g[bb]);
g[aa]+=g[bb];
f[bb]=aa;
}
}
ans[0]=n*(n-1);
for(i=1;i<=m;i++)
{
ans[i]=n*(n-1)-ans[i];
}
scanf("%d",&p);
while(p--)
{
scanf("%d",&t);
tt=lower_bound(q,q+m,t)-q;
printf("%d\n",ans[tt]);
}
}
return 0;
}
/*
题意:给定一个带有权值的图。两点的价值就是所有连接两点的路径的最小路径值。
路径值表示一个一条路径上的最大权值。输入一个t,问又多少对点价值大于等于t
方法:由于权值都不同,我们可以从小到大枚举权值c。判断权值为c的两点a,b
是否在同一个并查集内。若不是则合并两个点集。则点集中任何两个点的价值都小于等于c。
*/
hdu 4750 Count The Pairs 并查集+递推(2013 ACM/ICPC Asia Regional Nanjing Online 1003)
最新推荐文章于 2015-09-26 21:24:29 发布