连通分量:图的极大连通子图。
最小生成树(minimumcost spanning tree 即:MST):
n个点,n-1条边,构成一个连通图,求其中代价最小的连通图。
MST原理:
假设N={V,{E}}是一个连通图,设U是定点V的子集,设(a,b)是连通U和V-U的代价最小的边,其中a属于U,b属于V。那么定点集合V构成的最小生成树一定包含边(a,b)。
反证法:
假设T为顶点集合V的最小生成树,边(a,b)是连通U和A-U的代价最小的边,假设V的任何一棵最小生成树都不包含边(a,b)。将边(a,b)加入到T中后,会形成一个回路,则回路中必有一条边(c,d),且c属于U,d属于A-U。那么我们可以删除边(c,d),便构成一棵树R,则树R的代价一定不比T大,由于T是顶点集合V的所有最小生成树中任意一棵,如果边(a,b)是连通A-U和U的最小边,则T不是最小生成树。
Prim算法:
对于顶点集合V,初始状态划分成U={a},和V-U两个连通集合。每次选取连通两个集合中代价最小的边(c,d),并且c属于U,d属于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();
}