#include <iostream>
#include <vector>
#include <utility>
#include "DSU.hpp"
#include "MinHeap.hpp"
#include <algorithm>
using namespace std;
const int maxVertexNum = 20;
const int maxEdgeNum = 200;
const int INF = 65535;
const int vertexNum = 7;
int G[maxVertexNum][maxVertexNum] = {
{0, 10, INF, INF, INF, 2, INF },
{10, 0, 5, INF, INF, INF, INF },
{INF, 5, 0, 8, 1, 7, INF },
{INF, INF, 8, 0, 5, INF, INF },
{INF, INF, 1, 5, 0, 3, INF },
{2, INF, 7, INF, 3, 0, 1 },
{INF, INF, INF, INF, INF, 1, 0 }
};
// Prim
vector<pair<int, int> > Prim() {
bool used[vertexNum];
int mincost[vertexNum];
int sum = 0;
vector<pair<int, int> > res;
//初始化
for(int i = 0; i < vertexNum; ++i) {
mincost[i] = INF;
used[i] = false;
}
//从结点0开始
mincost[0] = 0;
for(int k = 0; k < vertexNum; ++k) {
//选最小
int min = INF;
int index;
for(int i = 0; i < vertexNum; ++i) {
if(!used[i] && min > mincost[i]) {
min = mincost[i];
index = i;
}
}
used[index] = true;
sum += mincost[index];
//存储从出发点到本点的权值,先后关系用线性表的前驱和后继关系表示
res.push_back(make_pair(sum, index));
//更新权值
for(int j = 0; j < vertexNum; ++j) {
if(mincost[j] > G[index][j])
mincost[j] = G[index][j];
}
}// end for
return res;
}
//Kruskal
class edge {
public:
unsigned int from, to, cost;
edge() {}
edge(int f, int t, int c):from(f), to(t), cost(c) {}
bool operator > (const edge & e) {
return cost > e.cost ? 1 : 0;
}
};
const int edgeNum = 9;
edge es[] = { edge(0,1,10), edge(0,5,2), edge(1,2,5), edge(2,3,8), edge(2,4,1), edge(2,5,7), edge(3,4,5), edge(4,5,3), edge(5,6,1) };
bool comp(const edge& e1, const edge& e2) {
return e1.cost < e2.cost;
}
vector<pair<edge,int> > Kruskal() {
vector< pair<edge, int> > res;
MinHeap<edge> minHeap(edgeNum);
for(int i = 0; i < edgeNum; i++)
minHeap.insert(es[i]);
//sort(es, es+edgeNum, comp);
DSU ufs(edgeNum);
int sum = 0;
for(int i = 0; i < edgeNum; ++i) {
edge temp = minHeap.removeMin();
//edge temp = es[i];
if(!ufs.same(temp.from, temp.to)) {
ufs.unite(temp.from, temp.to);
sum += temp.cost;
res.push_back(make_pair(temp, sum));
}
}
return res;
}
//Dijkstra
vector<unsigned int> dijkstra(int s) {
vector<unsigned int> d(vertexNum, INF);
d[s] = 0;
MinHeap<pair<int, int> > minHeap(100);
//pari<int, int> first是顶点路程,second是顶点编号
minHeap.insert(make_pair(0, s));
while(!minHeap.isEmpty()) {
pair<int, int> min = minHeap.removeMin();
if(min.first > d[min.second])
// 图中存在负权时,这个可能有用。
continue;
for(int i = 0; i < vertexNum; ++i) {
if(d[i] > d[min.second] + G[min.second][i]) {
d[i] = d[min.second] + G[min.second][i];
minHeap.insert(make_pair(d[i], i));
//cout << d[i] << " "<< i << endl;
}
}
}
return d;
}
void floyd() {
//vector<vector<int> > d(vertexNum, vector<int>(vertexNum, INF));
//int d[vertexNum][vertexNum];
for(int k = 0; k < vertexNum; ++k)
for(int i = 0; i < vertexNum; ++i)
for(int j = 0; j < vertexNum; ++j)
if(G[i][j] > G[i][k] + G[k][j])
G[i][j] = G[i][k] + G[k][j];
//return G;
}
int main() {
//MST, Minimum Spanning Tree
//prim
cout << "最小生成树——prim:" << endl;
vector<pair<int,int> > Prim_res = Prim();
for(auto i: Prim_res)
cout << "结点下标:"<< i.second << "," << " 目前权值总和为:" << i.first << endl;
cout << endl;
//Kruskal
cout << "最小生成树——kruskal:" << endl;
vector<pair<edge,int> > Kruskal_res = Kruskal();
for(auto i: Kruskal_res)
cout << "弧首:" << i.first.from
<< ", 弧尾:" << i.first.to
<< ", 权值:" << i.first.cost
<< ", 当前权和:" << i.second << endl;
cout << endl;
//single-source-minimum-path
//dijkstra
cout << "单源最短路径——dijkstra: " << endl;
cout << "请输入入口(0-6):" ;
int s;
cin >> s;
vector<unsigned int> dij = dijkstra(s);
for(int i = 0; i < dij.size(); ++i)
cout << "结点下标: "<< i << ", 路程:" << dij[i] << endl;
cout << endl;
//floyd
floyd();
cout << "多源最短路径——Floyd: " << endl;
//vector<vector<int> > floyd_res = floyd();
for(int i = 0; i < vertexNum; ++i) {
cout << "从结点" << i << "开始,到各个结点的路程:" << endl;
for(int j = 0; j < vertexNum; ++j) {
cout << " " << "到结点" << j << "的路程:" << G[i][j] << endl;
}
}
return 0;
}
图的相关算法实现
最新推荐文章于 2024-06-29 10:26:33 发布