图的相关算法实现

#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;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值