思路很简单,用kruskal算法生成最小生成森林。kruskal用并查集实现。用堆优化一下才能过。
#include<stdio.h>

//disjointset
int rank[1001],set[1001];

void Makeset(int x)

...{
set[x]=x;
rank[x]=0;
}
int Find(int x)

...{
if(set[x]!=x)
set[x]=Find(set[x]);
return set[x];
}
void Link(int x,int y)

...{
if(rank[x]>rank[y])
set[y]=x;

else...{
set[x]=y;
if(rank[x]==rank[y]) rank[y]++;
}
}
void Union(int x,int y)

...{
Link(Find(x),Find(y));
}
//disjointset end
typedef struct e

...{
int a,b,w;
}Edge;
Edge E[10001];

//MinHeap
int heapsize;
void heapify(int i)

...{
int l=i<<1;
int r=(i<<1) + 1;
int smallest;
if(l<heapsize && E[l].w<E[i].w) smallest=l;
else smallest=i;
if(r<heapsize && E[r].w<E[smallest].w) smallest=r;

if(smallest!=i) ...{
Edge tmp;
tmp=E[i];
E[i]=E[smallest];
E[smallest]=tmp;
heapify(smallest);
}
}
void Build(void)

...{
int i;
for(i=heapsize>>1;i>0;i--) heapify(i);
}
Edge Extract(void)

...{
Edge t;
t=E[1];
E[1]=E[heapsize];
heapsize--;
heapify(1);
return t;
}
//min heap end

int n,m,k;

int main(void)

...{
int i;
long cost=0;
Edge tmp;
FILE *fin=stdin;
fscanf(fin,"%d %d %d ",&n,&m,&k);
heapsize=m;
for(i=1;i<=m;i++)
fscanf(fin,"%d %d %d",&E[i].a,&E[i].b,&E[i].w);
Build();
for(i=1;i<=n;i++) Makeset(i);

for(i=n;i>k && heapsize;)...{
tmp=Extract();

if(Find(tmp.a)!=Find(tmp.b))...{
Union(tmp.a,tmp.b);
cost+=tmp.w;
i--;
}else continue;
}
if (i>k) printf("No Answer ");
else printf("%d ",cost);
return 0;
}
