首先这个题第一眼想到的是最小生成树,但他有k个树,那怎么办那?可以贪心一下。首先建图,将没有任何边得点的个数记录下来(kx),这些点自成一个集合,那么需要再建k-kx个树。
首先建一个最小生成树(共tail个边存入team【】中),那么建k-kx个树需要在最小生成树中拿走k-kx+1个边。因为要取最小花费,所以从最大的边减。
代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
int n,m,k,ta,f[100001],team[1000001],tail,kx,sum;
int exist[10001];
struct re
{
int next,w,t,s,head;
}e[10001*4];
void build(int x,int y,int z)
{
e[++ta].w=z;
e[ta].t=y;
e[ta].s=x;
e[ta].next=e[x].head;
e[x].head=ta;
}
bool cmp(re a,re b)
{
return a.w<b.w;
}
int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
void add(int a,int b)
{
int ux,uy; ux=find(a); uy=find(b);
f[ux]=uy;
}
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=m;++i)
{
int a,b,c;
cin>>a>>b>>c;
exist[a]=exist[b]=1;
build(a,b,c);
build(b,a,c);
}
for(int i=1;i<=n;++i)
{
f[i]=i;
if(exist[i]==0)
++kx;
}
k-=kx;
sort(e+1,e+ta+1,cmp);
for(int i=1;i<=ta;++i)
{
if(find(e[i].s)!=find(e[i].t))
{
add(e[i].s,e[i].t);
team[++tail]=i;
sum+=e[i].w;
}
}
for(int i=tail;i>(tail-k+1);--i)
{
sum-=e[team[i]].w;
}
if(n<(kx+k)||(kx+1)>k+kx)
cout<<"No Answer";
//如果点少于k或不在最小生成树中的点大于k则不成立。
else
cout<<sum;
return 0;
}