........................................................................................................................................................................................
只是最小生成树的变化,题意是将几个集合连在一起,求最小的路径;
..............................................................................................................
#include<stdio.h> #include <iostream> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> #include<list> #include<vector> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 550 int father[MAX]; int rank[MAX]; struct edge { int x; int y; int w; }; edge e[25005];//必须开大 bool cmp(edge o1,edge o2) { return o1.w<o2.w; } void Make_Set() { int i; for(i=1;i<=MAX;i++) { father[i]=i; rank[i]=0; } } int Find_Set(int x) { if(x!=father[x]) { father[x]=Find_Set(father[x]); } return father[x]; } int Union(int x,int y) { x=Find_Set(x); y=Find_Set(y); if(x==y) return 0; if(rank[x]<rank[y]) father[x]=y; else { father[y]=x; if(rank[x]==rank[y]) rank[x]++; } return 1; } int main() { int t,m,k,n,i,count; scanf("%d",&t); while(t--) { Make_Set(); scanf("%d%d%d",&n,&m,&k); { for(i=0;i<m;i++) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w); for(i=0;i<k;i++) { int t1,t2,tt; scanf("%d",&tt); scanf("%d",&t1); tt--; while(tt--) { scanf("%d",&t2); Union(t1,t2);//分步合并集合 } } sort(e,e+m,cmp); int sum=0; for(i=0;i<m;i++) { if(Union(e[i].x,e[i].y)) sum+=e[i].w; } count=0; for(i=1;i<=n;i++) { if(father[i]==i) count++; } if(count==1) printf("%d\n",sum); else printf("-1\n"); } } return 0; }