您的位置:首页 > 其它

最小生成树的总结

2010-10-23 17:00 330 查看
最小生成树有两种算法:kruskal算法与prim算法

http://acm.hdu.edu.cn/showproblem.php?pid=1102

kruskal算法如下:

//就是求最小生成树,对于已有的道路只要赋予0即可
//使用kruskal算法,对于每次都去找权值最小的边,如果不会形成环,则加入最小生成树的边
//对于判断是否形成环,则我们可以使用并查集的思想
#include<iostream>
#include<algorithm>
using namespace std;
#define M 101
#define inf 1<<20
struct node
{
int s, e, w;
}edge[M*M];
int mat[M][M];
int father[M], rank[M];//father[i]表示节点i的祖先编号,rank[i]表示i这个集合的个数
int n;//
void make_set()//初始化father[],rank[]
{
int i;
for(i=1; i<=n; i++)
{
father[i] = i;
rank[i] = 1;
}
}
int find_set(int x)//寻找x的祖先节点
{
if(x != father[x])
return father[x] = find_set(father[x]);
else
return x;
}
bool union_set(int x, int y)//合并x和y的集合
{
x = find_set(x);
y = find_set(y);
if(x == y)
return false;
if(rank[x] < rank[y])
{
father[x] = y;
rank[y] += rank[x];
}
else
{
father[y] = x;
rank[x] += rank[y];
}
return true;
}
bool cmp(const node &a, const node &b)//按权值进行排序
{
return a.w < b.w;
}
int main()
{
//	freopen("in.txt","r",stdin);
int i, q, a, b, j;
int ans;
while(scanf("%d",&n) != EOF)
{
make_set();
int m = 0;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
scanf("%d", &mat[i][j]);
}
}
scanf("%d",&q);
for(i=0; i<q; i++)
{
scanf("%d %d", &a, &b);
mat[a][b] = 0;
}
for(i=1; i<=n; i++)
{
for(j=i+1; j<=n; j++)
{
//	if(i == j)
//		continue;
edge[m].s = i;
edge[m].e = j;
edge[m++].w = mat[i][j];
//	printf("%d %d %d/n", i, j, mat[i][j]);
}
}
ans = 0;
sort(edge, edge+m, cmp);
for(i=0; i<m; i++)
{
if(union_set(edge[i].s, edge[i].e))//判断是否有环
ans += edge[i].w;
}
printf("%d/n",ans);
}
return 0;
}


prim算法如下:

//prim算法
//
#include<stdio.h>
#include<string.h>
#define M 101
#define inf 1<<20
int mat[M][M], lowcost[M];
bool v[M];
int n;
void prim()
{
int i, j, k, min;
int ans = 0;
for(i=1; i<=n; i++)
{
lowcost[i] = mat[1][i];
//		printf("%d/n", lowcost[i]);
v[i] = false;
}
v[1] = true;
for(i=2; i<=n; i++)
{
min = inf;
for(j=1; j<=n; j++)//寻找最小边
{
if(!v[j] && min > lowcost[j])
{
min = lowcost[j];
k = j;
}
}
v[k] = true;
//	printf("%d %d/n", min, k);
ans += min;
for(j=1; j<=n; j++)//更新最小边
{
if((mat[k][j] < lowcost[j]) && (!v[j]))
lowcost[j] = mat[k][j];
}
}
printf("%d/n", ans);
}
int main()
{
//	freopen("in.txt","r",stdin);
int i, j, q, a, b;
while(scanf("%d",&n) != EOF)
{
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
scanf("%d",&mat[i][j]);
scanf("%d",&q);
for(i=0; i<q; i++)
{
scanf("%d %d", &a, &b);
mat[a][b] = mat[b][a] = 0;
}
prim();
}
return 0;
}


两种算法在OJ上的比较:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: