zoukankan      html  css  js  c++  java
  • Prim和Kruskal求最小生成树

    Prim:

    算法步骤:

    1.任意结点开始(不妨设为v1)构造最小生成树: 2.首先把这个结点(出发点)包括进生成树里, 3.然后在那些其一个端点已在生成树里、另一端点还未在生成树里的所有边中找出权最小的一条边, 4.并把这条边、包括不在生成树的另一端点包括进生成树, …。 5.依次类推,直至将所有结点都包括进生成树为止

    Pascal的渣渣代码...

    注:寻找最短的边那一步可以用堆优化,但那样还不如直接用Kruskal......

    Reference:  http://www.nocow.cn/index.php/Prim%E7%AE%97%E6%B3%95

    const vmax=1000;
    var 
    w:array[1..vmax,1..vmax] of longint;
    i,j,k,v,e:longint;
    w:存储邻接矩阵
    v:结点数
    e:边数
    
    procedure prim(v0:longint);
    var flag:array[1..vmax] of boolean;  //flag:表示是否在树中。true是, false否
          min,prevk,nextk:longint;
    begin
     fillchar(flag,sizeof(flag),0);
     flag[v0]:=true;           //STEP2
     for i:=1 to v-1 do          //最小生成树中有v-1条边 ,所以外层循环需要v-1次        //STEP5
       begin
        min:=maxlongint;
    
        for k:=1 to v do  
          if flag[k] then  
            //寻找在最小生成树中的点  k:当前在最小生成树中的点
            for j:=1 to v do          //STEP3
              //寻找与(最小生成树中的点)的距离最短的点。
              // j:当前要找的不在最小生成树中的点 
              if (not flag[j]) and (w[k,j]<min) and (w[k,j]<>0) then
                紫色代码://判重:要找的点不能在最小生成树中
                红色代码://k与j必须相连!
                begin
                min:=w[k,j];
                nextk:=j;    
                prevk:=k;    
                //这条边从在最小生成树中的点出发 ,
                //扩展到当前不在最小生成树中的点。
                //prevk:=k,prevk为起点,在最小生成树中
                //nextk:=j,nextk为 终点,当前不在最小生成树中
                end;
    
        if min<>maxlongint then        
          //如果找到了nextk这样的可以从当前最小生成树中扩展出来
          //(可以进入最小生成树)的点
          begin
          flag[nextk]:=true;        //将nextk这样的点加入最小生成树    //STEP4
          writeln(prevk,‘ ’,nextk,‘ ’,min);           //输出这条边
          end;
       end;
    end;
    
    
    begin
    fillchar(w,sizeof(w),0);
    readln(v,e);
    for k:=1 to e do
     begin
     read(i,j);
     readln(w[i,j]);
     w[j,i]:=w[i,j];
     end;
    
    prim(1);       //STEP1
    
    end.
    View Code

    Kruskal:

    算法步骤:

    1、把图中的边按权值从小到大排序。 2、按从小到大的顺序依次向树中加边。       在添加每一条边(u,v)时,如果u和V两个点都已在树中,一旦添加,就回构成回路,所以放弃该边,在向后找下一条边。 3、直到添加n-1条边。

    用并查集优化

    #include <iostream>
    using namespace std;
    
    struct abc
    {
        int x,y,dat;
    };
    
    struct abc e[1000];
    int f[1000];
    int i,j,k,ans,n,m,tx,ty,tmp;
    
    int find(int x)
    {
        if (x!=f[x])
            f[x]=find(f[x]);
        return f[x];
    }
    
    void iunion(int x,int y)
    {
        int fx=find(x);
        int fy=find(y);
        if (fx!=fy)
            f[fy]=fx;
    }
    
    void qsort(int l,int r)
    {
       int i,j,mid;
       struct abc t; 
       i=l;
       j=r;
       mid=e[(l+r)/2].dat;
       do{
           while (e[i].dat<mid) i++;
           while (e[j].dat>mid) j--;
           if (!(i>j))
           {
               t=e[i];
               e[i]=e[j];
               e[j]=t;
               i++;
               j--;
           }
       }while (i<=j);
       if (l<j) qsort(l,j);
       if (i<r) qsort(i,r);
    }
    
    int main()
    {
        
        cin>>n>>m;
        for (i=1;i<=m;i++)
        {
            cin>>tx>>ty>>tmp;
            e[i].x=tx;
            e[i].y=ty;
            e[i].dat=tmp;
        }
    
        for (i=1;i<=n;i++)
            f[i]=i;
        qsort(1,m);
        
        k=1;
        ans=0;
        for (i=1;i<=n-1;i++)
        {
            while (find(e[k].x)==find(e[k].y)) k++;
            iunion(e[k].x,e[k].y);
            ans=ans+e[k].dat;
            cout<<e[k].x<<" "<<e[k].y<<" "<<e[k].dat<<endl;
        }
        
        cout<<ans<<endl;
    }
    View Code
  • 相关阅读:
    简单的html5 File base64 图片上传
    PHP CURL POST
    PHP常用代码段:
    使用Sqlserver事务发布实现数据同步(转)
    几个SQL小知识(转)
    Sql语句摘要
    C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe(转)
    说说C#的async和await(转)
    c#并发编程经典实例文摘
    [在职软件工程]数据挖掘-概念与技术
  • 原文地址:https://www.cnblogs.com/pdev/p/3869977.html
Copyright © 2011-2022 走看看