#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#define N 100090
using namespace std;
int n,m,t;
int pre[N];
struct node
{
int st,ed,val;
}e[N];
void init()
{
for(int i=0;i<=205;i++)
{
pre[i]=i;
}
}
int cmp(node a,node b)
{
return a.val<b.val;
}//从小到大排序
int Find(int m)
{
int n=m;
while(n!=pre[n])
n=pre[n];
//pre[m]=n;
return n;
}//查找根节点
void Merge(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx>fy)
pre[fx]=fy;
else
pre[fy]=fx;
}
int kruskal(int l)
{
int sum=0,cnt=t-1;
for(int i=0;i<l;i++)
{
if(Find(e[i].st)!=Find(e[i].ed))
{
cnt++;
Merge(e[i].st,e[i].ed);
sum+=e[i].val;
//printf("%d %d相连\n",e[i].st,e[i].ed);
//printf("%d的根节点是%d\n",e[i].st,Find(e[i].st));
//printf("%d的根节点是%d\n",e[i].ed,Find(e[i].ed));
}
if(cnt==n-1)
break;
}
return sum;
}
int main()
{
int T,k=1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&t);
init();
int a[N];
for(int i=0;i<t;i++)
{
scanf("%d",&a[i]);
if(i!=0)
{
Merge(a[i],a[i-1]);
//printf("%d和%d相连\n",a[i],a[i-1]);
//printf("%d的根节点是%d\n",a[i-1],Find(a[i-1]));
//printf("%d的根节点是%d\n",a[i],Find(a[i]));
}
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&e[i].st,&e[i].ed,&e[i].val);
}
sort(e,e+m,cmp);
printf("Case #%d: %d\n",k++,kruskal(m));
}
return 0;
}
题目大意:和基本的最小生成树想比,其在最开始的时候有多个起点,从任一起点开始生成都可以。提前把根节点都连起来就行了 ,剩下的和求最小声生成树一样。
注意:初始化问题。