hdu 5441 (2015长春网络赛E题 带权并查集 )

时间:2023-02-14 00:19:10

n个结点,m条边,权值是 从u到v所花的时间 ,每次询问会给一个时间,权值比 询问值小的边就可以走 从u到v 和从v到u算不同的两次 输出有多少种不同的走法(大概是这个意思吧)
先把边的权值 从小到大排序 询问值也按从小到大排序
num记录集合里元素的个数
每合并两个集合 ans增加 2*num[u]*num[v]

Sample Input
1
5 5 3 //n w q
2 3 6334
1 5 15724
3 5 5705
4 3 12382
1 3 21726
6000
10000
13000

Sample Output
2
6
12

 # include <iostream>
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <cmath>
# include <queue>
# define LL long long
using namespace std ; const int MAXN = ; int F[MAXN];
int num[MAXN] ;
int save[MAXN] ;
int n , m , q; struct Edge
{
int u ;
int v ;
int w ;
}e[MAXN * ]; bool cmp1(Edge x , Edge y)
{
return x.w < y.w ;
} struct Que
{
int id ;
int x ;
}a[MAXN]; bool cmp2(Que a , Que b)
{
return a.x < b.x ;
} int find(int x)
{
if(F[x]==x) return x;
return F[x]=find(F[x]);
}
void bing(int u,int v)
{
int x = find(u);
int y = find(v);
if ( y < x )
swap ( x , y );
F[y] = x;
num[x] += num[y];
} int main ()
{
//freopen("in.txt","r",stdin) ;
int T ;
scanf("%d" , &T) ;
while(T--)
{
int ans = ;
int j = ;
int i ;
scanf("%d%d%d" , &n , &m , &q) ;
for(i = ; i <= n ; i++)
{
F[i] = i ;
num[i] = ;
}
for(i = ; i < m ; i++)
scanf("%d%d%d" , &e[i].u , &e[i].v , &e[i].w) ;
sort(e , e+m , cmp1) ;
for(i = ; i < q ; i++)
{
scanf("%d" , &a[i].x) ;
a[i].id = i ;
}
sort(a,a+q,cmp2) ;
for(i = ; i < q ; i++)
{
while(j < m && e[j].w <= a[i].x)
{
int u = find(e[j].u);
int v = find(e[j].v);
j++ ;
if (u == v)
continue ;
ans += *num[u]*num[v] ;
bing(u,v) ;
}
save[a[i].id] = ans;
}
for(i = ; i < q ; i++)
printf("%d\n" , save[i]) ; } return ;
}