经过这三天对最小生成树的理论与实践的相互学习,我对最小生成树也有了一些了解,下面我来分享一下我的学习工程中的一些经验吧。
首先谈Kruskal,这个算法的大致思想就是,首先给你每两个城市之间的距离或其他的,总之是两个城市间的权值,然后让你搭建一条路径最短,费用最省的路,连接两个城市可以是直接连接,也可以是间接连接,因此不必要每两个城市之间都要修建一条路。
好下面开始上Kruskal的模板代码。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
struct edge
{
int u;
int v;
int w;
}que[20000];
int f[20000];
//对输入的对列进行排序,这个在我的另一篇博客中有提到,不懂去看我那篇博客
int cmp(edge a,edge b)
{
return a.w<b.w;
}
//用并查集来判断两个村庄之间是否需要建路
int getf(int v)
{
if(f[v]==v)
return v;
else
{
f[v]=getf(f[v]);
return f[v];
}
}
int merge(int x,int y)
{
int t1,t2;
t1=getf(x);
t2=getf(y);
if(t1!=t2)
{
f[t2]=t1;
return 1;
}
return 0;
}
int main()
{
int n,m,i,sum,count;
while(cin>>n>>m)
{
memset(f,0,sizeof(f));
sum=count=0;
for(i=0;i<m;i++)
cin>>que[i].u>>que[i].v>>que[i].w;
sort(que,que+m,cmp);
for(i=1;i<=n;i++)
f[i]=i;
for(i=0;i<m;i++)
{
if(merge(que[i].u,que[i].v))//判断两个村庄是否需要建路
{
count++;
sum+=que[i].w;
}
if(count==n-1)//n个村庄建n-1条路
break;
}
cout<<sum<<endl;
}
return 0;
}
prime算法的核心是dijkstra的模型思想也来源于dijkstra,唯一的不同就是在dis[v]>dis[u]+e[u][v],而prime中是判断dis[v]>e[u][v],你可能想知道这是为什么,好,现在给你答案,上面说了最小生成树中两个城市之间不一定非得有一条路,也就是说两个城市之间可以通过另一个城市间接连接起来,这也就是说每次在找到最近的u的时候就不需要在判断dis[u]的值l,因为在找到他之后u就已经被标记了,就表明他已经是树中的成员了,因此在下面的一个循环判断的时候就没有dis[u],也不需要它了。
prime模板:
#include<stdio.h>
#include<string.h>
int e[20000][20000],dis[20000],book[20000];
int inf=99999999;
int main()
{
int sum,i,j,k,min,n,t1,t2,t3,m,v;
while(scanf("%d%d",&n,&m)!=EOF)
{
sum=0;
memset(book,0,sizeof(book));
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);
if(t3<e[t1][t2])
e[t1][t2]=e[t2][t1]=t3;
}
for(i=1;i<=n;i++)
dis[i]=e[1][i];
book[1]=1;
for(v=1;v<n;v++)
{
min=inf;
for(i=1;i<=n;i++)
{
if(book[i]==0&&dis[i]<min)
{
min=dis[i];
j=i;
}
}
book[j]=1;
sum+=dis[j];
for(k=1;k<=n;k++)
if(book[k]==0&&dis[k]>e[j][k])
dis[k]=e[j][k];
}
printf("%d\n",sum);
}
return 0;
}