最小生成树(prim+kruskal)

prim

prim算法:找到和这个集合距离最小的点并入集合,然后再找和这个集合距离最小的点(已经在集合内的不能算)

使用for循环,遍历一个点进行两种更新:一、更新这个点到集合最短距离 二、更新所有点到集合的最短距离。找到距离集合最近的点并入集合。
当边数=点数-1时,跳出循环。

#include
#include
#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 
#include 
#include 
#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;
}

你可能感兴趣的:(acm模板/常用算法)