用Kruskal算法計算最小生成樹時,將結點分成不同的集合,一開始所有的結點都在不同的集合
將所有的邊排序后(按照權值進行從小到大排序) 然后看每邊的兩個結點是否屬於不同集合,
如果不是,則可以將這條表加到最小生成樹中,並把這兩個結點放到同一個集合中,然后如此類推,
直到最小生成樹中有了n-1條邊
測試用例:
上面說的那個集合,我用兩個map來實現,好久沒敲C++的代碼,寫的不好請見諒
Edge.h
#ifndef GUARD_Edge_h
#define GUARD_Edge_h
#include <string>
using std::string;
class Edge
{
public:
Edge() {}
Edge(const string& StartNode,const string& EndNode, double weight):
StartNodeID(StartNode),EndNodeID(EndNode),Weight(weight) {}
string StartNodeID;
string EndNodeID;
double Weight;
};
bool Compare(const Edge& e1,const Edge& e2);
#endif
Node.h
#ifndef GUARD_Node_h
#define GUARD_Node_h
#include <string>
#include <vector>
#include "Edge.h"
using std::string;
using std::vector;
//結點以及這個結點所有的出邊
class Node
{
public:
Node(const string& ID,const vector<Edge>& edgeList) :
_ID(ID),_edgeList(edgeList) {}
Node(const string& ID):_ID(ID) {}
string GetID()
{
return _ID;
}
vector<Edge> GetEdgeList()
{
return _edgeList;
}
void AddEdge(const Edge& edge)
{
_edgeList.push_back(edge);
}
private:
string _ID;
vector<Edge> _edgeList;
};
#endif
Graph.h
#ifndef GRUAD_Graph_h
#define GRUAD_Graph_h
#include <string>
#include <map>
#include <vector>
#include "Node.h"
#include "MSTree.h"
using std::string;
using std::map;
using std::vector;
class Graph
{
typedef map<string,double> Path;
typedef map<string,Path> G;
public:
Graph(const vector<Node>& nodeList):
_nodeList(nodeList) {};
MSTree GetMST();
private:
G graph;
vector<Node> _nodeList;
};
#endif
Graph.cpp
#include "Graph.h"
#include <iostream>
#include <algorithm>
using namespace std;
MSTree Graph::GetMST()
{
G s;//集合s
vector<Node>::size_type i;
vector<Node>::size_type j;
//儲存所有邊的容器
vector<Edge> edgeList;
//初始化s集合,使每個頂點分屬於不同的集合
for (i=0;i<_nodeList.size();i++)
{
string NodeID=_nodeList[i].GetID();
s[NodeID][NodeID]=1;
for (j=0;j<_nodeList[i].GetEdgeList().size();j++)
edgeList.push_back((_nodeList[i].GetEdgeList())[j]);
}
//把邊按照權值進行從小到大排序
sort(edgeList.begin(),edgeList.end(),Compare);
/*for (vector<Edge>::size_type ii=0;ii<edgeList.size();ii++)
{
cout<<edgeList[ii].StartNodeID<<"->"<<edgeList[ii].EndNodeID
<<" "<<edgeList[ii].Weight<<endl;
}*/
vector<Node>::size_type k=1; //計數
vector<Edge>::size_type d=0;
string m1,m2; //記錄一條邊的兩個頂點分別在哪個集合
j=0;
vector<Edge> Tree; //儲存最小生成樹的邊
double weight=0; //以及總權值
while(k<_nodeList.size())
{
for (i=0;i<_nodeList.size();i++)
{
string curNodeID=_nodeList[i].GetID();
if (s[curNodeID][edgeList[d].StartNodeID]==1)
m1=curNodeID;
if(s[curNodeID][edgeList[d].EndNodeID]==1)
m2=curNodeID;
}
//如果一條邊的兩個頂點屬於不同的集合
//就把這條邊加到樹中
if (m1!=m2)
{
//cout<<m1<<" "<<m2<<endl;
Tree.push_back(edgeList[d]);
weight+=edgeList[d].Weight;
k++;
for (j=0;j<_nodeList.size();j++)
{
// 合並兩個集合
s[m1][_nodeList[j].GetID()]=s[m1][_nodeList[j].GetID()]
||s[m2][_nodeList[j].GetID()];
// 將另一個集合置空
s[m2][_nodeList[j].GetID()]=0;
}
}
d++;
}
MSTree msTree(Tree,weight);
return msTree;
}
MSTree.h
#ifndef GUARD_MSTree_h
#define GUARD_MSTree_h
#include <vector>
#include "Edge.h"
using std::vector;
//最小生成樹,含有n-1條邊以及
//所有邊的總權值
class MSTree
{
public:
MSTree(const vector<Edge>& edgeList,double weight):
_msTree(edgeList),_weight(weight){}
vector<Edge> GetEdgeList() {return _msTree;}
double GetWeight() {return _weight;}
private:
vector<Edge> _msTree;
double _weight;
};
#endif
main.cpp
#include <iostream>
#include "Graph.h"
#include <map>
#include <vector>
using namespace std;
vector<Node> Init()
{
Edge edge;
Node A("A");
edge.StartNodeID="A";
edge.EndNodeID="B";
edge.Weight=8;
A.AddEdge(edge);
edge.StartNodeID="A";
edge.EndNodeID="D";
edge.Weight=5;
A.AddEdge(edge);
Node B("B");
edge.StartNodeID="B";
edge.EndNodeID="D";
edge.Weight=3;
B.AddEdge(edge);
edge.StartNodeID="B";
edge.EndNodeID="E";
edge.Weight=10;
B.AddEdge(edge);
edge.StartNodeID="B";
edge.EndNodeID="C";
edge.Weight=12;
B.AddEdge(edge);
Node C("C");
edge.StartNodeID="C";
edge.EndNodeID="E";
edge.Weight=6;
C.AddEdge(edge);
edge.StartNodeID="C";
edge.EndNodeID="F";
edge.Weight=2;
C.AddEdge(edge);
Node D("D");
edge.StartNodeID="D";
edge.EndNodeID="F";
edge.Weight=7;
D.AddEdge(edge);
edge.StartNodeID="D";
edge.EndNodeID="G";
edge.Weight=15;
D.AddEdge(edge);
Node E("E");
edge.StartNodeID="E";
edge.EndNodeID="F";
edge.Weight=9;
E.AddEdge(edge);
Node F("F");
Node G("G");
vector<Node> nodeList;
nodeList.push_back(A);
nodeList.push_back(B);
nodeList.push_back(C);
nodeList.push_back(D);
nodeList.push_back(E);
nodeList.push_back(F);
nodeList.push_back(G);
return nodeList;
}
int main()
{
vector<Node> nodeList=Init();
Graph graph(nodeList);
MSTree msTree=graph.GetMST();
//得到計算結果
vector<Edge> edgeList=msTree.GetEdgeList();
cout<<"Minimum Spanning Tree: "<<endl;
for (vector<Edge>::size_type i=0;i<edgeList.size();i++)
{
cout<<edgeList[i].StartNodeID<<"->"<<edgeList[i].EndNodeID
<<" "<<edgeList[i].Weight<<endl;
}
cout<<"Total weight: "<<msTree.GetWeight()<<endl;
return 0;
}
結果:
於是我們得到的最小生成樹為: