最小生成树

1.Kruskal算法

首先选择最短的边,再选择次短的边,直到连通,若两个点已经用过就不再用了

判断两个顶点是否连通:并查集

 int father[maxn+1];

 int getf(int v)

{

  if(father[v]==v)

      return v;

  else

     return father[v]=getf(father[v]);

}

 int merge(int u,int v)

 {

    int t1=getf(u);

   int t2=getf(v);

   if(t1!=t2)

  {

     f[t2]=f[t1];

     return 1;

  }

  return 0;

 }

Kruskal核心部分:

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

 f[i]=1;

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

 {

    if(merge(e[i].u,e[i].v])

      {

         count++;

         sum+=e[i].w;

     }

    if(count==n-1)

     break;

 }

 cout<<sum<<endl;

 

2.Prim算法

把所有的点分为两部分:已经生成加入集合的,还未加入的,每次寻找离所有生成集合中任意一点最近的点加入生成的集合

为了找点,类似Dijkstra算法,利用辅助数组,不过更新方法变为靠近生成的点组成的集合,而不是某一固定点

 

代码为://假设从1号点开始

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

  dis[i]=e[1][i];

 book[1]=1;

 count++;

While(count<n)

 {

   min=INF;

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

    {

        if(book[i]==0&&dis[i]<min)

       {

       min=dis[i];

         mark=i;

          }

      book[mark]=1;

      count++;

     sum+=dis[mark];

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

       if(boo[j]==0&&dis[j]>a[mark][j]

         dis[j]=a[mark][j];

   }

 }

 cout<<sum<<endl;

 

 

 

 

 

原文地址:https://www.cnblogs.com/wtblogwt/p/10585084.html