prim
prim算法:找到和这个集合距离最小的点并入集合,然后再找和这个集合距离最小的点(已经在集合内的不能算)
使用for循环,遍历一个点进行两种更新:一、更新这个点到集合最短距离 二、更新所有点到集合的最短距离。找到距离集合最近的点并入集合。
当边数=点数-1时,跳出循环。
#include<iostream>
#include<algorithm>
#define maxn 100
using namespace std;
int n,m;
int edge[maxn][maxn];
int dis[maxn];//每个点到集合的最短距离
int vis[maxn];//判断这个点是否被加入
int prim()
{
//先把第一个点放进去
for(int i=1;i<=n;i++)
dis[i]=edge[1][i];
for(int i=1;i<=n;i++)
vis[i]=0;
vis[1]=1;//1就是并入这个集合
dis[1]=0;
int count=0;
int e=1;
int minn=1e9;
int ans=0;
while(1)
{
minn=1e9;
if(count==n-1)
break;
int temp;
for(int i=1;i<=n;i++)
{
if(vis[i]!=1)
{
if(edge[e][i]<dis[i])//更新最近距离
{
dis[i]=edge[e][i];
}
if(minn>dis[i])
{
temp=i;
minn=dis[i];
}
}
}
e=temp;
ans+=dis[e];
count++;
vis[e]=1;
}
return ans;
}
int main()
{
cin>>n>>m;
//输入边的邻接矩阵
int a,b;//边
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
edge[i][j]=1e9;
}
for(int i=0;i<m;i++)
{
cin>>a>>b;
cin>>edge[a][b];
edge[b][a]=edge[a][b];
}
int ans=prim();
cout<<ans<<endl;
}
kruskal:
详解
用并查集实现
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#define N 150
using namespace std;
int m,n,u[N],v[N],w[N],p[N],r[N];
int cmp(const int i,const int j) {return w[i]<w[j];}
int find(int x) {return p[x]==x?x:p[x]=find(p[x]);}
int kruskal()
{
int cou=0,x,y,i,ans=0;
for(i=0;i<n;i++) p[i]=i;
for(i=0;i<m;i++) r[i]=i;
sort(r,r+m,cmp);
for(i=0;i<m;i++)
{
int e=r[i];x=find(u[e]);y=find(v[e]);
if(x!=y) {ans += w[e];p[x]=y;cou++;}
}
if(cou<n-1) ans=0;
return ans;
}
int main()
{
int i,ans;
while(scanf("%d%d",&m,&n)!=EOF&&m)
{
for(i=0;i<m;i++)
{
scanf("%d%d%d",&u[i],&v[i],&w[i]);
}
ans=kruskal();
if(ans) printf("%d\n",ans);
else printf("?\n",ans);
}
return 0;
}