题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3938
思路:对于边进行从小到大进行排序,题目要求a、b两点之间所有的路径中的最大边的最小值,在满足边的大小<=len的条件下,令r1=Find(a),r2=Find(b),若r1==r2,此时就是简单的合并,并且更新一下集合的个数(abs(parent[i])即为以i为根结点的集合的大小),若r1!=r2,此时a,b两点之间的路径的条数即为parent[r1]*parent[r2]。显然对于那些边>=len的,都要加上原先的路径数目。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN 10000+100 7 #define MAXM 50000+555 8 typedef long long LL; 9 int parent[MAXN]; 10 int n,m,q; 11 LL path[MAXN]; 12 struct Edge{ 13 int u,v,w; 14 }edge[MAXM]; 15 16 struct Node{ 17 int id,len; 18 }p[MAXN]; 19 20 int Find(int x) 21 { 22 int s; 23 for(s=x;parent[s]>=0;s=parent[s]) 24 ; 25 while(x!=s){ 26 int tmp=parent[x]; 27 parent[x]=s; 28 x=tmp; 29 } 30 return s; 31 } 32 33 int Union(int u,int v) 34 { 35 int r1=Find(u),r2=Find(v); 36 if(r1==r2)return 0; 37 int tmp=parent[r1]*parent[r2]; 38 if(parent[r1]<parent[r2]){ 39 parent[r1]+=parent[r2]; 40 parent[r2]=r1; 41 }else { 42 parent[r2]+=parent[r1]; 43 parent[r1]=r2; 44 } 45 return tmp; 46 } 47 48 int cmp1(const Edge &a,const Edge &b) 49 { 50 return a.w<b.w; 51 } 52 53 int cmp2(const Node &a,const Node &b) 54 { 55 return a.len<b.len; 56 } 57 58 59 int main() 60 { 61 while(~scanf("%d%d%d",&n,&m,&q)){ 62 memset(parent,-1,sizeof(int)*(n+2)); 63 for(int i=0;i<m;i++){ 64 scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); 65 } 66 sort(edge,edge+m,cmp1); 67 for(int i=0;i<q;i++){ 68 scanf("%d",&p[i].len); 69 p[i].id=i; 70 } 71 sort(p,p+q,cmp2); 72 LL ans=0; 73 int pos=0; 74 for(int i=0;i<q;i++) 75 { 76 while(pos<m&&edge[pos].w<=p[i].len){ 77 ans+=Union(edge[pos].u,edge[pos].v); 78 pos++; 79 } 80 path[p[i].id]=ans; 81 } 82 for(int i=0;i<q;i++) 83 printf("%I64d\n",path[i]); 84 } 85 return 0; 86 }