hdu 5441 (2015长春网络赛E题 带权并查集 )
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
1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6 # include <queue> 7 # define LL long long 8 using namespace std ; 9 10 const int MAXN = 20010; 11 12 int F[MAXN]; 13 int num[MAXN] ; 14 int save[MAXN] ; 15 int n , m , q; 16 17 struct Edge 18 { 19 int u ; 20 int v ; 21 int w ; 22 }e[MAXN * 5]; 23 24 bool cmp1(Edge x , Edge y) 25 { 26 return x.w < y.w ; 27 } 28 29 struct Que 30 { 31 int id ; 32 int x ; 33 }a[MAXN]; 34 35 bool cmp2(Que a , Que b) 36 { 37 return a.x < b.x ; 38 } 39 40 int find(int x) 41 { 42 if(F[x]==x) return x; 43 return F[x]=find(F[x]); 44 } 45 void bing(int u,int v) 46 { 47 int x = find(u); 48 int y = find(v); 49 if ( y < x ) 50 swap ( x , y ); 51 F[y] = x; 52 num[x] += num[y]; 53 } 54 55 int main () 56 { 57 //freopen("in.txt","r",stdin) ; 58 int T ; 59 scanf("%d" , &T) ; 60 while(T--) 61 { 62 int ans = 0 ; 63 int j = 0 ; 64 int i ; 65 scanf("%d%d%d" , &n , &m , &q) ; 66 for(i = 1 ; i <= n ; i++) 67 { 68 F[i] = i ; 69 num[i] = 1 ; 70 } 71 for(i = 0 ; i < m ; i++) 72 scanf("%d%d%d" , &e[i].u , &e[i].v , &e[i].w) ; 73 sort(e , e+m , cmp1) ; 74 for(i = 0 ; i < q ; i++) 75 { 76 scanf("%d" , &a[i].x) ; 77 a[i].id = i ; 78 } 79 sort(a,a+q,cmp2) ; 80 for(i = 0 ; i < q ; i++) 81 { 82 while(j < m && e[j].w <= a[i].x) 83 { 84 int u = find(e[j].u); 85 int v = find(e[j].v); 86 j++ ; 87 if (u == v) 88 continue ; 89 ans += 2*num[u]*num[v] ; 90 bing(u,v) ; 91 } 92 save[a[i].id] = ans; 93 } 94 for(i = 0 ; i < q ; i++) 95 printf("%d\n" , save[i]) ; 96 97 } 98 99 return 0 ; 100 }