........................................................................................................................................................................................
只是最小生成树的变化,题意是将几个集合连在一起,求最小的路径;
..............................................................................................................
#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;
}