最小生成树模板

最小生成树模板

Prim算法

第一种形式(邻接矩阵)

const int MAXN=110;
struct Node
{
  int adjvex;
  int lowcost;
}closedge[MAXN];
int cost[MAXN][MAXN];
int MinV_Ucost(int n)   //这个函数是用来找V集合的点到U集合点的最短cost(当然是只有两个点)
{                       //(1~n)
    int MINN=0x3f3f3f3f;
    int i,v;
    for(i=1;i<=n;i++)
    {
      if(closedge[i].lowcost!=0)   //等于0的就已经进U集合了,不做考虑,这样避免了生成环。
      {
          if(closedge[i].lowcost<MINN)
          {
              MINN=closedge[i].lowcost;
              v=i;
          }

      }
    }
    if(MINN==0x3f3f3f3f)
    {
         printf("不连通\n");  //原图不连通,至少有一个不为INF才连通啊
         return 0;
    }
    else
    return v;
}
int Prim(int u,int n)    //u是U集合的第一个点,可以认为假设
{
    int i,j;
    int v;
    int ans=0;
    closedge[u].lowcost=0; //=0就是将该结点放入U集合中
    for(i=1;i<=n;i++)
    {
        if(i!=u)
        {
          closedge[i].adjvex=u;  //i是在V集合中的点,同时说明第一个点是没有adjvex的
          closedge[i].lowcost=cost[u][i];
        }
    }
    for(j=1;j<n;j++) //第一个点已经确定,进入U,还剩n-1个点没进U集合
    {
        v=MinV_Ucost(n);
        ans+=closedge[v].lowcost;
        /*u=closedge[v].adjvex;   //这样就多了个可以输出两邻接点的功能
        printf("%d %d\n",u,v);*/
        closedge[v].lowcost=0;    //把新点加入U集合。
        for(i=1;i<=n;i++)        //更新V各点到U各点的最短距离。
        {
            if(cost[v][i]<closedge[i].lowcost)  //在U中的点是0,所以if语句无视
            {
                closedge[i].lowcost=cost[v][i];
                closedge[i].adjvex=v;
            }
        }
    }
      return ans;
}

第二种形式 

const int INF=0x3f3f3f3f;
const int MAXN=110;
bool vis[MAXN];
int lowc[MAXN];
int cost[MAXN][MAXN];
int Prim(int n)//点是0~n-1
{
   int ans=0;
   memset(vis,false,sizeof(vis));
   vis[0]=true;
   for(int i=1;i<n;i++)
   lowc[i]=cost[0][i];
   for(int i=1;i<n;i++)
   {
      int minc=INF;
      int p=-1;
      for(int j=0;j<n;j++)
      if(!vis[j]&&minc>lowc[j])
      {
        minc=lowc[j];
        p=j;
      }
      if(minc==INF)return -1;//原图不连通,至少有一个不为INF才连通啊
      ans+=minc;
      vis[p]=true;
      for(int j=0;j<n;j++)
      if(!vis[j]&&lowc[j]>cost[p][j])
      lowc[j]=cost[p][j];
  }
     return ans;
}


Kruskal算法 (邻接矩阵优化)

const int MAXN=110;//最大点数
const int MAXM=20000;//最大边数
int F[MAXN];//并查集使用
struct Edge
{
    int u,v,w;
}edge[MAXM];//存储边的信息,包括起点/终点/权值
int tol;//边数,加边前赋值为0
void addedge(int u,int v,int w) //邻接矩阵的优化结构
{
  edge[tol].u=u;
  edge[tol].v=v;
  edge[tol++].w=w;          //多组测试数据的话,tol每次都要清0
}
bool cmp(Edge a,Edge b)
{//排序函数,讲边按照权值从小到大排序
   return a.w<b.w;
}
int find(int x)
{
  if(F[x]==-1)
  return x;
  else
  return
  F[x]=find(F[x]);
}
int Kruskal(int n)//传入点数,返回最小生成树的权值,如果不连通返回-1
{
     memset(F,-1,sizeof(F));
     sort(edge,edge+tol,cmp);
     int cnt=0;//计算加入的边数
     int ans=0;
     for(int i=0;i<tol;i++)
    {
       int u=edge[i].u;
       int v=edge[i].v;
       int w=edge[i].w;
       int t1=find(u);
       int t2=find(v);
         if(t1!=t2)          //利用并查集改变顶点集合状态
       {
        ans+=w;
        F[t1]=t2;
        cnt++;
       }
       if(cnt==n-1)         //n个结点,n-1条边,所以只要合并n-1次即可
       break;
    }
      if(cnt<n-1)
      return -1;//不连通
      else
      return ans;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值