1. 程式人生 > >求無向連通圖的最小生成樹(c語言版)

求無向連通圖的最小生成樹(c語言版)

完整原始碼地址:[email protected]:hglspace/MinCostSpTree.git

圖例:

                   

1 普里姆演算法

/*

 普里姆演算法:假設N={v,{E}}是連通圖,TE是N上的最小生成樹中邊的集合,演算法從U={u0}(u0屬於V),TE={}開始,重複執行下述操作:

 在所有u屬於U,v屬於V-U的邊<u0,v0>屬於E中找一條代價最小的邊(u0,v0)併入集合TE,直至U=V為止,此時TE中必有n-1條邊,則T={V,{TE}}為N的最小生成樹

 */

void MiniSpanTree_PRIM(structGraph

g,structvert u){

    struct tmp closedge[MAX_VEX_NUM];

    int index=u.index,i,j;

    int minimum(structtmp closedge[]);

for(j=0;j<g.vexnum;j++){//初始化輔助陣列,輔助陣列是記錄從U到V-U具有最小代價的邊

        if(j!=index){

            closedge[j].lowcost=g.arcs[index][j].cost;

            closedge[j].vex=u;

        }

    }

    closedge[index].lowcost=0;//自己到自己的最小權值是0

    for(i=1;i<g.vexnum;i++){

        index=minimum(closedge);

        if(index<0){

            printf("此圖不是連通圖\n");

            exit(0);

        }

        printf("下一個頂點是:%c,權值是:%d\n",g.vexs[index].data,closedge[index].lowcost);

        closedge[index].lowcost

=0;

for(j=0;j<g.vexnum;j++){//U中有增加了新頂點,比較closedge陣列中的最小權值和該頂點到V-U其他頂點的權值

            if(g.arcs[index][j].cost<closedge[j].lowcost){

                closedge[j].lowcost=g.arcs[index][j].cost;

                closedge[j].vex=g.vexs[index];

            }

        }

    }

}

int minimum(structtmp closedge[]){//求closedge陣列中最小權值的邊,返回V-U中的頂點位置

    int i,tlow=999,index=-1;

    for(i=0;i<MAX_VEX_NUM;i++){

        if(tlow>closedge[i].lowcost && closedge[i].lowcost>0){

            tlow=closedge[i].lowcost;

            index=i;

        }

    }

    return index;

}

2 克魯斯卡爾演算法

/*

 克魯斯卡爾:假設連通圖N={v,{E}},則令最小生成樹的初始狀態為只有n個頂點而無邊的非連通圖T={v,{}},圖中每個頂點自稱一個連通分量。在E中選擇代價最小的邊,

 若該邊依附的頂點落在T中不同的連通分量上,則將此邊加入到T中,否則捨去此邊而選擇下一條代價最小的邊。以此類推,直至T中所有的頂點都在同一連通分量上為止。

 */

void MiniSpanTree_KRUSKAL(structGraph g){//把當前圖用鄰接多重連結串列儲存?

//把鄰接矩陣結構儲存的圖轉化為鄰接多重連結串列結構,原因是:方便下面查詢兩個頂點是否在同一個連通圖中,並且會多次遍歷查詢

    int i,j,n=1;

    struct arc getMinArc(structGraph * g,structAmGraph amg);

    struct arc a;

    struct AmGraph amg={};

    for(i=0;i<g.vexnum;i++){

        struct VexBox v;

        v.data=g.vexs[i].data;

        v.firstedge=NULL;

        v.mark=False;

        amg.vb[i]=v;

    }//初始化後,所有的頂點都是孤立的,並沒有任何邊

//按照定義開始選擇邊

while(n<g.vexnum){//最小生成樹的邊,必定比頂點數少一個

        struct Ebox * e=(structEbox *)malloc(sizeof(structEbox));

        a=getMinArc(&g,amg);//把找到的邊存放到多重連結串列結構的圖中

        e->cost=a.cost;

        e->ivex=a.head;

        e->jvex=a.tail;

        e->ilink=NULL;

        e->jlink=NULL;

        e->mark=False;

//把a新增到amg中

        if(amg.vb[a.head].firstedge==NULL){

            amg.vb[a.head].firstedge=e;

        }else{

            e->ilink=amg.vb[a.head].firstedge;

            amg.vb[a.head].firstedge=e;

        }

        if(amg.vb[a.tail].firstedge==NULL){

            amg.vb[a.tail].firstedge=e;

        }else{

            e->jlink=amg.vb[a.tail].firstedge;

            amg.vb[a.tail].firstedge=e;

        }

        n++;

    }

    for(i=0;i<g.vexnum-1;i++){

        for(j=i+1;j<g.vexnum;j++){

if(g.arcs[i][j].cost==0){//找到合適的邊,會把其權值置為0,這裡根據這個特點輸出

                printf("頭頂點:%c,尾頂點:%c,權值是:%d\n",g.vexs[i].data,g.vexs[j].data,g.arcs[i][j].tmpcost);

            }

        }

    }

}

/*

  獲取合適的邊

 */

struct arc getMinArc(structGraph * g,structAmGraph amg){

    int i,j,head,tail,tmp=999;

    struct arc a;

    Bool judgeLt(int head,int tail,structAmGraph g);

    for(i=0;i<g->vexnum-1;i++){

        for(j=i+1;j<g->vexnum;j++){

            if(g->arcs[i][j].cost>0 && tmp>g->arcs[i][j].cost){

                head=g->arcs[i][j].head;

                tail=g->arcs[i][j].tail;

Vexflag=False;//在每次呼叫判斷兩個頂點是否在同一連通分量的方法之前,一定要把全域性變數Vexflag置為False,排除上一次查詢的結果的干擾

                if(judgeLt(head,tail,amg)){

                    continue;

                }

                tmp=g->arcs[i][j].cost;

                a=g->arcs[i][j];

            }

        }

    }

    g->arcs[a.head][a.tail].tmpcost=g->arcs[a.tail][a.head].tmpcost=a.cost;

    g->arcs[a.head][a.tail].cost=g->arcs[a.tail][a.head].cost=0;

    return a;

}

/*

 判斷該邊依附的兩個頂點是否在同一連通分量上

 */

Bool judgeLt(int head,int tail,structAmGraph g){

//遍歷該圖,判斷這兩個頂點是否在一個連通分量上

    Bool DFSTree(structAmGraph g,int v1,int v2,structEbox * ebs[]);

    struct Ebox * ebs[MAX_EDG_NUM]={};

    int i;

    Bool flag=DFSTree(g,head,tail,ebs);

//一定要把amg的邊的mark再置為False,下次再呼叫,mark還是預設值,每次查詢,多重連結串列圖都應該是原始的,標誌變數一定要改回原來的狀態

    for(i=0;ebs[i]!=NULL;i++){

        ebs[i]->mark=False;

    }

    return flag;

}

Bool DFSTree(structAmGraph g,int v1,int v2,structEbox * ebs[]){

    int i;

    int getAdjVex(structAmGraph * g,int v,structEbox * ebs[]);

    for(i=getAdjVex(&g,v1,ebs);i>0;i=getAdjVex(&g,v1,ebs)){

if(!g.vb[i].mark){//其實這個判斷不加也行,加這個判斷主要是排除兩個頂點之間有迴路的情況,而現在的情況是這兩個頂點之間不會有迴路的

            g.vb[i].mark=True;

            if(i==v2){

                Vexflag=True;

            }

        }

        DFSTree(g, i, v2,ebs);

    }

returnVexflag;

}

/*

  獲取該頂點的鄰接頂點

 */

int getAdjVex(structAmGraph * g,int v,structEbox * ebs[]){

    int i;

    for(i=0;ebs[i]!=NULL;i++);

    struct Ebox * e=g->vb[v].firstedge;

    if(e==NULL){

        return -1;

    }

    for(;e!=NULL&&e->mark==True;){

        if(e->ivex==v){

            e=e->ilink;

        }else{

            e=e->jlink;

        }

    }

    if(e==NULL){

        return -1;

    }else{

        ebs[i]=e;//把遍歷過的邊,放在esb陣列中,呼叫結束後,把該邊的狀態置為原始值

        e->mark=True;

        if(e->ivex==v){

            return e->jvex;

        }else{

            return e->ivex;

        }

    }

}


相關推薦

連通小生成樹(c語言)

完整原始碼地址:[email protected]:hglspace/MinCostSpTree.git 圖例:                     1 普里姆演算法 /*  普里姆演算法:假設N={v,{E}}是連通圖,TE是N上的最小生成樹中邊的集合

連通小割點詳解以及java原始碼實現

import java.util.*; /**尋找割點*/ public class FindArt { static class Node { Node(String name) { this.name=name; Childen=new Arra

連通的割點

1. 割點與連通度 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。一個沒有關節點的連通圖稱為重連通圖(biconnected graph)。若在連通圖上

論】連通的割點

1. 割點與連通度 在無向連通圖中,刪除一個頂點v及其相連的邊後,原圖從一個連通分量變成了兩個或多個連通分量,則稱頂點v為割點,同時也稱關節點(Articulation Point)。一個沒有關節點的連通圖稱為重連通圖(biconnected graph)。若在連通圖上至少刪去k 個頂點才能破壞圖的連通性,則

用Tarjan演算法連通割點&&割邊

/** 割點割邊挺好理解的,割點就是一個無向連通圖,把其中一個點 挖掉剩下的圖不連通,割邊就是把一條邊砍掉不連通 比如:有一個通訊網路,要求一顆炸彈,把這個通訊網路搞得不連通,問 炸哪個點或哪條邊。 Tarjan 演算法實現求割邊

所有邊權均不相同的小生成樹是唯一的證明

eight weight nbsp 不同的 權重 cnblogs 成了 http 方法 設G是所有邊權均不相同的無向聯通圖。 證明一: 首先,易證圖G中權值最小的邊一定是最小生成樹中的邊。(否則最小生成樹加上權值最小的邊後構成一個環,去掉環中任意一條非此邊則形成了另一

1212 小生成樹

alt 時間 難度 布爾 too 數組 star tar += 1212 無向圖最小生成樹 基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題 收藏 關註 N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 In

51 nod 1212 小生成樹(Kruckal演算法/Prime演算法圖解)

1212 無向圖最小生成樹 N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。  收起 輸入 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 -

51nod 1212 小生成樹

數量 color def main tdi ring () return print N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 輸入 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N &l

論)51NOD 1212 小生成樹

N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 輸入 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 - M + 1

51Nod1212 小生成樹

#include<iostream> #include<cstring> #include<cstdio> using namespace std; int map[

51nod 1212 小生成樹(Kruskal演算法)

 收藏  關注 N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 Input 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 5

51nod 1212 小生成樹小生成樹

 收藏  關注 N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 Input 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 &

小生成樹(prim演算法)

輸入 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000, 1 <= M <= 50000) 第2 - M + 1行:每行3個數

51nod 1212 小生成樹prim演算法

N個點M條邊的無向連通圖,每條邊有一個權值,求該圖的最小生成樹。 Input 第1行:2個數N,M中間用空格分隔,N為點的數量,M為邊的數量。(2 <= N <= 1000

leetcode 847. Shortest Path Visiting All Nodes 連通遍歷短路徑

sel shu turn 判斷 lam 最短 額外 動態 訪問 設計最短路徑 用bfs 天然帶最短路徑 每一個狀態是 當前的階段 和已經訪問過的節點 下面是正確但是超時的代碼 class Solution: def shortestPathLength(self,

[帶標號連通計數 容斥原理 多項式逆 多項式ln 模板題] BZOJ 3456 城市規劃

可以通過容斥求出答案的表示式fi=2C2i−∑j=1i−1Cj−1i−1∗fj∗2C2i−j 其中前一部分表示i個點任意連邊 後半部分列舉1所在的連通塊然後容斥掉 ∑j=1ifj(j−1)!∗2C2i−j(i−j)!=2C2i(i−1)! 這是個卷積的

小生成樹

基礎:無向圖的kruskal演算法 摘抄: 最 小樹形圖,就是給有向帶權圖中指定一個特殊的點root,求一棵以root為根的有向生成樹T,並且T中所有邊的總權值最小。最小樹形圖的第一個演算法是 1965年朱永津和劉振巨集提出的複雜度為O(VE)的演算法。 判斷是否存在樹形圖

小生成樹——小樹形圖(朱…

對於有向圖的最小生成樹 , 也叫做最小樹形圖 。 最小樹形圖的第一個演算法是1965年朱永津和劉振巨集提出的複雜度為O(VE)的演算法。 值得我們驕傲啊 。 下面來分享這個演算法 。 1、求最小樹形圖之前一定要確定根 , 確定根之後再去驗證是否存在樹形圖(這個很簡單 , 就是從根節點能不能到其他點)

poj1523 SPF 連通 割點 關節點 tarjan演算法

SPF Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 5103 Accepted: 2347 Description Consider the two networks shown below.