克鲁斯卡尔算法(Kruskal):是一种用来寻找最小生成树的算法。在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。
它的思想是:先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。
代码实现:
#include<stdio.h>
struct edge
{
int u;
int v;
int w;
};
struct edge e[10];
int m,n;
int f[7] = {0};sum = 0,count = 0;
void quicksotr(int left, int right)
{
int i,j;
struct edge t;
if(left > right)
return ;
i = left;
j = right;
while(i != j)
{
while(e[j].w >= e[left].w && i < j)
j --;
while(e[i].w <= e[left].w && i < j)
i ++;
if(i < j)
{
t = e[i];
e[i] = e[j];
e[j] = t;
}
}
t = e[left];
e[left] = e[i];
e[i] = t;
quicksotr(left, i-1);
quicksotr(i+1, right);
return ;
}
int getf(int v)
{
if(f[v] == v)
return v;
else
{
f[v] = getf(f[v]);
return f[v];
}
}
int merge(int v, int u)
{
int t1,t2;
t1 = getf(v);
t2 = getf(u);
if(t1 != t2)
{
f[t2] = t1;
return 1;
}
return 0;
}
int main()
{
int i;
scanf("%d%d",&n,&m);
for(i = 1; i <= n; 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] = 1;
for(i = 1; i <= m; i ++)
{
if(merge(e[i].u,e[i].v))
{
count ++;
sum += e[i].w;
}
if(count == n-1)
break;
}
printf("%d",sum);
return 0;
}
普里姆算法(Prim):
算法思路: 首先就是从图中的一个起点a开始,把a加入U集合,然后,寻找从与a有关联的边中,权重最小的那条边并且该边的终点b在顶点集合:(V-U)中,我们也把b加入到集合U中,并且输出边(a,b)的信息,这样我们的集合U就有:{a,b},然后,我们寻找与a关联和b关联的边中,权重最小的那条边并且该边的终点在集合:(V-U)中,我们把c加入到集合U中,并且输出对应的那条边的信息,这样我们的集合U就有:{a,b,c}这三个元素了,一次类推,直到所有顶点都加入到了集合U。
代码实现:
#include<stdio.h>
int m,n,count=0,sum=0,e[110][110],dis[110],book[110] = {0};
int inf = 99999999;
void Prim()
{
int i,j,k,min;
for(i = 1; i <= n; i ++)
dis[i] = e[1][i];
book[1] = 1;
count ++;
while(count < n)
{
min = inf;
for(i = 1; i <= n; i ++)
if(book[i] == 0 && dis[i] < min)
{
min = dis[i];
j = i;
}
book[j] = 1;
count ++;
sum += dis[j];
for(k = 1; k <= n; k ++)
if(book[k] == 0 && dis[k] > e[j][k])
dis[k] = e[j][k];
}
}
int main()
{
int i,j,t1,t2,t3;
while(scanf("%d%d",&n,&m) != EOF)
{
for(i = 1; i <= n; i ++)
for(j = 1; j <= n; j ++)
if(i == j)
e[i][j] = 0;
else
e[i][j] = inf;
for(i = 1; i <= m; i ++)
{
scanf("%d%d%d",&t1,&t2,&t3);
e[t1][t2] = e[t2][t1] = t3;
}
Prim();
printf("%d\n",sum);
}
return 0;
}