您的位置:首页 > 其它

最小生成树算法

2016-10-09 11:31 169 查看
一、目的;

找图中连通所有点的n-1条边;

二、prim算法;

1) 将所有点都断开,然后选择一个点作为起始点,V代表已经连通的最小生成树中的点,S代表不在V里面的点,每次选择S中离V最近的点;最终将所有的点加入V中。

2) 证明:假设我们每次加入的那一条边不是最小边时的为最小生成树,那么我们将最小边加入,会形成一个环,在这个环中任意去掉比最小边要大的边构成的生成树更小,与假设不符,故命题可证

 3)

#include<stdio.h>

#define MAX 999999

int map[10][10];

int n,m;

void init()

{

int i,j;

scanf("%d%d",&n,&m);

for (i=1;i<=n;i++)

for (j=1;j<=n;j++)

map[i][j]=MAX;

for(i=1;i<=m;i++)

{

int x,y,z;

scanf("%d%d%d",&x,&y,&z);

map[x][y]=z;

map[y][x]=z;

}

}

void prim()

{

int i,j;

int ans=0;

int v[10]={0};

int d[10];

for (i=1;i<=n;i++)

d[i]=map[1][i];

v[1]=1;

for (i=1;i<=n-1;i++)

{

int min=MAX,minj;

for(j=1;j<=n;j++)

if(!v[j]&&min>d[j])

{

min=d[j];

minj=j;

}

v[minj]=1;

ans+=min;

for (j=1;j<=n;j++)

if(!v[j]&&d[j]>map[minj][j])

{

d[j]=map[minj][j];

}

}

printf("Prim : %d\n",ans);

}

int main()

{

init();

prim();

return 0;

}


三、kruskal算法

1) 本算法是通过对所有边排序之后,从小到大依次添加到最小生成树中,首先判断两点是否在连通,不连通则加入,其判断用并查集优化。

 2)

#include<stdio.h>

#include<algorithm>

using namespace std;

struct Node

{

int v,u,value;

} edge[100];

int f[100];

int n,m;

bool cmp(Node a,Node b)

{

return a.value<b.value;

}

void init()

{

int i,j;

scanf("%d%d",&n,&m);

for (i=1;i<=m;i++)

scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].value);

sort(edge+1,edge+m+1,cmp);

for (i=1;i<=n;i++) f[i]=i;

}

int find(int x)

{

if(f[x]==x) return x;

else return f[x]=find(f[x]);

}

void kruskal()

{

int i;

int ans=0;

for(i=1;i<=m;i++)

{

int x=find(edge[i].u);

int y=find(edge[i].v);

if(x!=y){

ans+=edge[i].value;

f[find(x)]=find(f[y]);

}

}

printf("Kruskal: %d\n",ans);

}

int main()

{

init();

kruskal();

return 0;

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