1.2 Kruskal
问题
在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得到的 w(T) 最小,则此 T 为 G 的最小生成树。
解析
先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。
#include<stdio.h>
struct edge
{
int u;
int v;
int w;
};
struct edge e[1000];
int n,m;
int f[1000]={0},sum=0,count=0;
void quicksort(int l,int r)
{
int i,j;
struct edge t;
if(l>r)
return;
i=l;
j=r;
while(i!=j)
{
while(e[j].w>=e[l].w&&i<j)
j–;
while(e[i].w<=e[l].w&&i<j)
i++;
if(i<j)
{
t=e[i];
e[i]=e[j];
e[j]=t;
}
}
t=e[l];
e[l]=e[i];
e[i]=t;
quicksort(l,i-1);
quicksort(i+1,r);
return;
}
int getf(int v)
{
if(f[v]v)
return v;
else
{
f[v]=getf(f[v]);
return f[v];
}
}
int blending(int v,int u)
{
int t,p;
t=getf(v);
p=getf(u);
if(t!=p)
{
f[p]=t;
return 1;
}
return 0;
}
int main()
{
int i;
scanf("%d %d",&n,&m);
for(i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
quicksort(1,m);
for(i=1;i<=n;i++)
f[i]=i;
for(i=1;i<=m;i++)
{
if(blending(e[i].u,e[i].v))
{
count++;
sum+=e[i].w;
}
if(countn-1)
break;
}
printf("%d\n",sum);
return 0;
}