#include <iostream>
#include <vector>
#include <queue>
#include <fstream>
#include <string>
using namespace std;
//union-find class
class UF{
private:
vector<int> id;
vector<int> sz;
int count;
public:
UF(int N)
{
count = N;
for(int i=0;i<N;i++){
id.push_back(i);
sz.push_back(1);
}
}
int countComps(){
return count;
}
bool connected(int p,int q){
return findId(p)==findId(q);
}
int findId(int p){
while(p != id[p]){
id[p] = id[id[p]];
p = id[p];
}
return p;
}
void unionComps(int p,int q){
int i = findId(p);
int j = findId(q);
if(i == j) return;
if (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; }
count--;
}
};
//Weighted Edge and its Graph
struct Edge{
int v;
int w;
double weight;
};
using EdgeLine = vector<Edge>;
class EdgeWeightedGraph{
public:
EdgeWeightedGraph(int V){
this->V = V; this->E = 0;
for(int v=0;v<V;v++){
EdgeLine el;
adj.push_back(el);
}
}
EdgeWeightedGraph(string fileIn)
{
ifstream fin(fileIn);
fin>>V>>E;
for(int v=0;v<V;v++){
EdgeLine el;
adj.push_back(el);
}
const int edges = E;
for(int i=0;i<edges;i++){
Edge tmp;
fin>>tmp.v>>tmp.w>>tmp.weight;
adj[tmp.v].push_back(tmp);
adj[tmp.w].push_back(tmp);
E++;
}
}
int getV() {return V;}
int getE() {return E;}
void addEdge(Edge e){
int v = e.v, w = e.w;
adj[v].push_back(e);
adj[w].push_back(e);
E++;
}
EdgeLine getEdgeLine(int v){
return adj[v];
}
private:
int V;
int E;
vector<EdgeLine> adj;
};
//Edge compare struct
struct CmpEdge{
bool operator()(Edge& e1,Edge& e2){
return e1.weight > e2.weight;
}
};
using MST = queue<Edge>;
class KruskalMST{
public:
KruskalMST(EdgeWeightedGraph G)
{
//MinPQ
priority_queue<Edge, vector<Edge>, CmpEdge> pq;
for(int i=0;i<G.getV();i++){
EdgeLine el = G.getEdgeLine(i);
for(auto x : el){
if(x.v==i) {pq.push(x);}
}
}
//UF
UF uf(G.getV());
while(!pq.empty() && (mst.size() < G.getV()-1)){
Edge e = pq.top();
pq.pop();
int v=e.v,w=e.w;
if(uf.connected(v,w)) continue;
uf.unionComps(v,w);
mst.push(e);
}
}
MST edges() {return mst;}
double weight(){
double wt = 0.0;
while(!mst.empty()){
Edge e = mst.front();
wt += e.weight;
mst.pop();
}
return wt;
}
private:
MST mst;
};
int main(int argc,char *argv[])
{
string filename = argv[1];
//cout<<"Input filename:"<<endl;
//cin>>filename;
EdgeWeightedGraph G(filename);
KruskalMST klMST(G);
MST mst = klMST.edges();
/*
while(!mst.empty()){
Edge e = mst.front();
cout<<e.v<<"-"<<e.w<<" "<<e.weight<<endl;
mst.pop();
}
*/
cout<<"Edges in the mst: "<<mst.size()<<endl;
cout<<"Weight of the mst: "<<klMST.weight()<<endl;
return 0;
}
程序运行结果测试:
1.
date +%s.%N;./graphpa.exe tinyEWG.txt;date +%s.%N
1450197763.375439900
Edges in the mst: 7
Weight of the mst: 1.81
1450197763.479829700
2.
date +%s.%N;./graphpa.exe mediumEWG.txt;date +%s.%N
1450197826.173859800
Edges in the mst: 249
Weight of the mst: 10.4635
1450197826.300132800
3.
date +%s.%N;./graphpa.exe largeEWG.txt;date +%s.%N
1450197882.677610400
Edges in the mst: 999999
Weight of the mst: 647.663
1450197913.652838600
测试数据在这下载:
http://algs4.cs.princeton.edu/code/