最小生成树,然后看他有多少个连通分量,每个连通分量有个飞机场,最后看所有剩下的边是否有大于飞机场的费用,有的话,改成飞机场;
比赛的时候一直没想明白,╮(╯▽╰)╭;
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100009
using namespace std;
int n,m,a;
struct edge
{
int u,v,w;
bool operator<(const edge& t)const
{
return w<t.w;
}
}ed[maxn];
int f[],pen[],ans,cnt;
int find(int x)
{
return x==f[x]?x:f[x]=find(f[x]);
} bool kruskal()
{
for(int i=;i<m;i++)
{
int x=find(ed[i].u);
int y=find(ed[i].v);
if(x!=y)
{
f[x]=y;
pen[cnt++]=ed[i].w;
ans+=ed[i].w;
}
}
} int main()
{
int ca=,num,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&m,&a);
ans=num=cnt=;
memset(pen,,sizeof pen);
for(int i=;i<=n;i++)f[i]=i;
for(int i=;i<m;i++)
scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].w);
sort(ed,ed+m);
kruskal();
for(int i=;i<=n;i++)if(i==find(i))num++;
for(int i=;i<=cnt;i++)
if(pen[i]>=a)
{
num++;
ans-=pen[i];
}
ans+=num*a;
printf("Case #%d: %d %d\n",ca++,ans,num);
}
return ;
}