图的最小生成树

连通分量:图的极大连通子图。

最小生成树(minimumcost spanning tree 即:MST):

        n个点,n-1条边,构成一个连通图,求其中代价最小的连通图。

MST原理:

        假设N={V,{E}}是一个连通图,设U是定点V的子集,设(ab)是连通UV-U的代价最小的边,其中a属于Ub属于V。那么定点集合V构成的最小生成树一定包含边(ab)。

反证法:

        假设T为顶点集合V的最小生成树,边(ab)是连通UA-U的代价最小的边,假设V的任何一棵最小生成树都不包含边(ab)。将边(ab)加入到T中后,会形成一个回路,则回路中必有一条边(cd),且c属于Ud属于A-U。那么我们可以删除边(cd),便构成一棵树R,则树R的代价一定不比T大,由于T是顶点集合V的所有最小生成树中任意一棵,如果边(ab)是连通A-UU的最小边,则T不是最小生成树。

Prim算法:

        对于顶点集合V,初始状态划分成U={a},和V-U两个连通集合。每次选取连通两个集合中代价最小的边(cd),并且c属于Ud属于A-U,并把顶点d并入集合U中。直到U=V为止。

Kruskal算法:

        对于顶点集合V,初始状态为每个顶点都设为一个连通分量,每次选取连接连通分量的最小的边,并且合并这两个连通分量,直到合并为一个连通分量为止。

 


注意把图看成无向图,而且输入的矩阵必须是无向图,即对称矩阵.

最小生成树

Prim_mst算法+kruskal算法:

 

#include<iostream>
#include<deque>
#include<queue>
 
usingnamespace std;
 
typedefchar VextexType;
typedefint  EdgeType;
 
#defineVexNum 5
structEdgeNode;
structEdgeNode {
    VextexType HeadName;
    VextexType TailName;
    EdgeType  weight;
    EdgeNode  *VexOut;
    EdgeNode  *VexIn;
    bool operator < (const EdgeNode&node)const {
        return weight > node.weight;
    }
};
 
 
 
typedefstruct
{
    VextexType name;
    EdgeNode  *VexOutlink;
    EdgeNode  *VexInlink;
}VexNode;
 
VexNodeadjList[VexNum];
boolvisit[VexNum];
intfather[VexNum];
intrank_set[VexNum];
 
voidcreatGraph()
{
 
    VextexType vextemp;
    EdgeType  edgetemp;
    char a[]={'A','B','C','D','E'};
 
    int b[] = { 0, 2, 9, 54, 0,
                2, 0, 0, 0,  13,
                9 ,0 ,0 ,5, 0,
                54,0, 5, 0,  8,
                0 ,13,0 ,8 , 0};
    //input n vextex
    for ( int i=0; i<VexNum ; ++i ){
        cin>>vextemp;
        //vextemp = a[i];
        adjList[i].name       = vextemp;
        adjList[i].VexOutlink = NULL;
        adjList[i].VexInlink  = NULL;
    }
    for ( int i=0; i<VexNum*VexNum; ++i ){
        cin>>edgetemp;
        //edgetemp = b[i];
        if ( edgetemp==0 ){
            continue;
        }
 
        EdgeNode *pEdge = new EdgeNode;
        pEdge->HeadName =adjList[i/VexNum].name;
        pEdge->TailName =adjList[i%VexNum].name;
        pEdge->weight   = edgetemp;
 
        pEdge->VexOut   = adjList[i/VexNum].VexOutlink;
        if ( pEdge->VexOut ){
            while ( pEdge->VexOut->VexOut){
                pEdge->VexOut=pEdge->VexOut->VexOut;
            }
            pEdge->VexOut->VexOut =pEdge;
            pEdge->VexOut=NULL;
        } else {
            adjList[i/VexNum].VexOutlink =pEdge;
            pEdge->VexOut = NULL;
        }
    }
    for ( int i=0 ;i<VexNum ;++i ){
        EdgeNode **pInLink =&adjList[i].VexInlink;
        for ( int j=0; j<VexNum; ++j ){
            if ( i==j ){
                continue;
            }
            EdgeNode *p =adjList[j].VexOutlink;
            while ( p ){
                if ( p->TailName !=adjList[i].name ){
                    p = p->VexOut;
                    continue;
                }
                *pInLink = p;
                pInLink = &p->VexIn;
                p = p->VexOut;
            }
        }
        *pInLink = NULL;
    }
}
 
voiddestroyGrape()
{
    for ( int i=0; i<VexNum ;++i ){
        EdgeNode *p = adjList[i].VexOutlink;
        EdgeNode *q;
        while ( p ){
            q = p;
            p = p->VexOut;
            delete q;
        }
    }
 
 
}
 
voidprintGrape()
{
    for ( int i=0; i<VexNum; ++i ){
       cout<<adjList[i].name<<"-->";
        EdgeNode *p = adjList[i].VexOutlink;
        while ( p ){
           cout<<"("<<p->HeadName<<","<<p->TailName<<","<<p->weight<<")";
            p = p->VexOut;
        }
        cout<<endl;
        p = adjList[i].VexInlink;
       cout<<adjList[i].name<<"-->";
        while ( p ){
           cout<<"("<<p->HeadName<<","<<p->TailName<<","<<p->weight<<")";
            p = p->VexIn;
        }
        cout<<endl;
 
    }
}
 
voidMST_Prim()
{
    unsigned int bitMap = 1;
    int elemtNum = 1;
    deque<EdgeNode*> s;
    EdgeNode *p;
    EdgeNode* pEdge = NULL;
    for ( int elemtNum=1; elemtNum<VexNum;++elemtNum  ){
        pEdge = NULL;
        if ( elemtNum<=VexNum/2 ){      
            for ( int i=0 ; i<VexNum ; ++i){
                if ( ~bitMap & 1<<i){
                    continue;
                }
                p = adjList[i].VexOutlink;
                while ( p ){
                    //后继节点在同一个集合中或者当前最小边比当前边小.
                    if ( (bitMap &(1<<(p->TailName-'A'))) || (pEdge &&  pEdge->weight< p->weight) ){
                        p = p->VexOut;
                        continue;        
                    }
                    pEdge = p;
                    p = p->VexOut;
                }
            }
            bitMap |=1<<(pEdge->TailName-'A');
        } else {
            for ( int i=0; i<VexNum ;++i ){
                if ( bitMap & 1<<i ){
                    continue;
                }
                p = adjList[i].VexOutlink;
                while ( p ){
                    //后继节点在同一个集合中或者当前最小边比当前边小.
                    if ( ( ~bitMap &(1<<(p->TailName-'A'))) || ( pEdge && pEdge->weight <p->weight )  ){
                        p = p->VexOut;
                        continue;
                    }
                    pEdge = p;
                    p = p->VexOut;
                }
            }
            bitMap |=1<<(pEdge->HeadName-'A');
        }
        if ( !pEdge ){
           cout<<"error"<<endl;
            //exit(0);
        }
        s.push_back(pEdge);
       
    }
 
    while ( !s.empty() ){
        p = s.front();
        s.pop_front();
       cout<<"("<<p->HeadName<<","<<p->TailName<<","<<p->weight<<")";
    }
    cout<<endl;
 
}
 
voidmake_set(int x)
{
    father[x] = x;
    rank_set[x]   = x;
}
 
intfind_father(int x)
{
    if ( father[x]!=x ){
        father[x] = find_father(father[x]);
    }
    return father[x];
}
 
voidUnion(int x,int y)
{
    x = find_father(x);
    y = find_father(y);
    if ( x==y ){
        return ;
    }
    if ( rank_set[x]>rank_set[y]  ){
        father[x] = father[y];
    } else{
        if ( rank_set[x]==rank_set[y] ){
            rank_set[y]++;
        }
        father[x]=y;
    }
 
}
 
voidMST_Kruskal()
{
   
    EdgeNode *p;
    EdgeNode tempEdge;
    priority_queue<EdgeNode>que;
    deque<EdgeNode> s;
   
    int countNum=1;
    for ( int i=0; i<VexNum; ++i ){
        make_set(i);
    }
   
    for ( int i=0; i<VexNum; ++i ){
        p = adjList[i].VexOutlink;
        while ( p ){
            que.push(*p);
            p = p->VexOut;
        }
    }
 
    while ( countNum<VexNum ){
        tempEdge = que.top();
        que.pop();
        p = &tempEdge;
       
        //线段的两个顶点在同一个集合
        if ( find_father(p->HeadName-'A') ==find_father(p->TailName-'A') ){
            continue;
        }
     
        //线段的两个顶点在在同一个集合,合并
       Union(p->HeadName-'A',p->TailName-'A');
        s.push_back(*p);
        countNum++;
    }
 
    while ( !s.empty()){
        tempEdge = s.front();
        s.pop_front();
        p=&tempEdge;
       cout<<"("<<p->HeadName<<","<<p->TailName<<","<<p->weight<<")";
    }
    cout<<endl;
}
 
 
int main()
{
    creatGraph();
    printGrape();
    MST_Prim();
    MST_Kruskal();
    destroyGrape();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值