zoukankan      html  css  js  c++  java
  • 最小生成树

    1. 无向图与开放树

      在讲最小生成树之前,先来说一说开放树。连通而无环路的无向图称做开放树。如果指定开放树中某一顶点为根,并且把每一条边看成是背离根的,则一棵开放树变成一棵树。

    开放树有2个性质:

    • 具有n>=1个顶点的开放树包含n-1条边
    • 如果在开放树中任意增加一条边,将构成一个环路

    如下列两个图:

    image_1be1se15l19kkj7f15k6plugod9.png-7.8kB

    2. 最小生成树

    只针对无向图

      假设E中的每条边都有权重,为c(u,v),也叫做边长。图G的一棵生成树是连接V中所有顶点的一棵开放树。将生成树中所有边长的总和称为生成树的价。使这个价最小的生成树称为图的最小生成树

      设G=(V,E)是一个连通图,在E上定义一个权函数C,且{(V1,T1),(V2,T2),...,(Vk,Tk)}是G的任意生成森林,令

        image_1be1srah117bj110t91lc8v17q7m.png-2.5kB

      其中,|T| <= |E|,又假设e=(v,w)是E-T中的一条边,其权值C[v][w]最小,而且v在V1中,w不在V1中,则图G有一棵包含T和e的生成树,其价不大于包含T的任何生成树的价。

    以上的性质下,两种算法应运而生:Prim算法和Kruskal算法

    • Prim算法
        /*输入为加权无向图G=(V,E),其中V={1,2,3,...,n}
         要点:引进集合U和T,U准备放顶点,T准备放边。初值为U={1},T为空,选择最小权的边(u,v),使u在U中,v在V-U中,将v加入U,(u,v)加入T。重复这个过程 */
         
         
         void Prim(costtype C[n+1][n+1])
         {
            /*CLOSECT表示U中的顶点,(i,CLOSECT[i])具有最小的权,而LOWCOST[i]表示该边的权,其中i不在U中  */
            
            costtype LOWCOST[n+1];
            int CLOSEST[n+1];
            int i,j,k;
            costtype min;
            for(i=2;i <= n;i++)
            {
                //初始化
                LOWCOST[i] = C[1][i];
                CLOSEST[i] = 1;
            }
            
            for(i=2;i=n;i++)
            {
                min = LOWCOST[i];
                k=i;
                //找出最小权的边
                for(j=2;j<=n;j++) {
                    if(LOWCOST[j] < min) {
                        min = LOWCOST[j];
                        k = j;
                    }
                cout<<"("<<k<<","<<CLOSECT[k] << ")"<<endl;
                LOWCOST[k] = infinity;  /* k加入U */
                
                
                //对新加入的k的基础上,更新LOWCOST和CLOSECT
                for(j = 2;j<=n;j++) {
                    if(C[k][j] < LOWCOST[j] && LOWCOST[j] != infinity) {
                        LOWCOST[j] = C[k][j];
                        CLOSECT[j] = k;
                    }
                }
            }
         }
    
    • Kruskal算法
        void Kruskal(V,T)
        {
            T = V;
            ncomp = n;
            while(ncomp > 1) {
                从E中取出并删除权最小的边(v,u)
                if(v和u属于T中不同的连通分量) {
                    T= T + (v,u);
                    ncomp --;
                }
            }
        }
    

    Prim算法复杂度为O(n2),而Kruskal算法复杂度为O(ne),故Prim算法适用于点较少的情况

    3. 最小树形图

    只针对有向图

      首先为除根之外的每个点选定一条入边,这条入边一定要是所有入边中最小的。现在所有的最小入边都选择出来了,如果这个入边集不存在有向环的话,我们可以证明这个集合就是该图的最小树形图。这个证明并不是很难。如果存在有向环的话,我们就要将这个有向环缩成一个人工顶点,同时改变图中边的权。假设某点u在该环上,并设这个环中指向u的边权是in[u],那么对于每条从u出发的边(u, i, w),w为权,在新图中连接(new, i, w)的边,其中new为新加的人工顶点; 对于每条进入u的边(i, u, w),在新图中建立边(i, new, w-in[u])的边。

    image_1be20ei6d1dh91r02rb6r9fa5p13.png-250.9kB

        int ZLEdmonds(int n,int map[maxn][maxn])  
        {  
            bool visited[maxn],flag[[maxn];  
            int pre[maxn];  
            int sum=0,i,j,k;  
            for( i=0; i<n; i++){  
                 flag[i]=false;  
                 map[i][i]=INF;  
            }  
            pre[0]=0;  
            while( true){  
                   //求最短弧集合E0。  
                   for( i=1; i<n; i++){  
                        if( flag[i]) continue;  
                        pre[i]=i;  
                        for( j=0; j<n; j++){   //pre[i]保存终点为i的最短弧的起点。  
                             if( !flag[j]&&map[j][i]<map[pre[i]][i])  
                                 pre[i]=j;      
                        }  
                        if( pre[i]==i) return -1;  
                   }   
                   //检查E0  
                   for( i=1; i<n; i++){  
                        if( flag[i]) continue;  
                        for( j=0; j<n; j++)  
                             visited[j]=false;  
                        visited[0]=true;  
                          
                        j=i;  
                        do{  
                            visited[j]=true;  
                            j=pre[j];  
                        }while( !visited[j]);   
                        if( !j) continue; //没有找到环。  
                           
                        i=j;//将整个环的权值保存,累计入原图的最小树形图  
                        do{  
                            sum+=map[pre[j]][j];  
                            j=pre[j];  
                        }while( j!=i);  
                          
                        j=i;//对于环上的点有关的边,修改边权  
                        do{  
                            for( k=0; k<n; k++){  
                                 if( !flag[k]&&map[k][j]&&map[k][j]<INF&&k!=pre[j])  
                                     map[k][j]-=map[pre[j]][j];  
                            }  
                            j=pre[j];  
                        }while( j!=i);  
                          
                        //缩点,将整个环缩成i号点,所有环上的点有关的边转移到点i  
                        for( j=0; j<n; j++){  
                             if( j==i) continue;  
                             for( k=pre[i]; k!=i; k++){  
                                    
                                  if( map[k][j]<map[i][j])  
                                      map[i][j]=map[k][j];  
                                  if( map[j][k]<map[j][i])  
                                      map[j][i]=map[j][k];   
                             }  
                        }  
                        //标记环上其他的点为被缩掉  下次再找Ei时不参与   
                        for( j=pre[i]; j!=i; j=pre[j])  
                             falg[j]=true;  
                        //当前环缩点结束,形成新的图G',跳出继续求G'的最小树形图 ,累计入sum。   
                   }   
                   if( i==n){  
                       for( i=0; i<n; i++)  
                            if( !flag[i])  
                                sum+=map[pre[i]][i];  
                       break;  
                   }  
            }          
                 return sum;          
        }  
    
  • 相关阅读:
    DEDECMS里面DEDE函数解析
    dede数据库类使用方法 $dsql
    DEDE数据库语句 DEDESQL命令批量替换 SQL执行语句
    织梦DedeCms网站更换域名后文章图片路径批量修改
    DSP using MATLAB 示例 Example3.12
    DSP using MATLAB 示例 Example3.11
    DSP using MATLAB 示例 Example3.10
    DSP using MATLAB 示例Example3.9
    DSP using MATLAB 示例Example3.8
    DSP using MATLAB 示例Example3.7
  • 原文地址:https://www.cnblogs.com/vachester/p/6732054.html
Copyright © 2011-2022 走看看