Dijkstra

把链式图和矩阵图的Dijkstra写了一下。矩阵图用二维数组保存的,链式图用一维vector数组保存的。

#include <bits/stdc++.h>
#define INF 99999999
using namespace std;
/*
    过程变量:
        int length;     //原点到顶点的最短路径
        int visit;      //标记顶点,分成两个集合
*/
/*
    算法思路:
        假设两个集合,起点s,终点v。一个集合保存已知最短路径的顶点(S),初始为空;一个保存不知
        最短路径的顶点(T),初始为全集。实际操作时采取设标识符的方法。首先把 s加入S,然后每次
        向外搜索最短路径时把此时距s最近的顶点加入S,加入后更新length,直到加入的是v;
*/
/*
    伪码:
        初始化 s的过程变量 
        循环vertexNum次:
            求出当前最短路径对应的顶点 
            如果是v,则退出
            循环vertexNum次:
                更新过程变量
*/
/*
    拓展:
        1)求点到顶点的最短路径个数
        2)求点到顶点走过的路径
        3)最短路径是边权最小,若在边权最小时还需要点权最小,可以补充边权 
*/
/*
    补充过程变量:
        int num;        //原点到顶点的路径个数
        vector<int> pre;        //原点到顶点走过的路径
        int weight;     //原点到顶点的另一标准:点权 
*/
class Help
{
    public:
        int visit, length, num;
        vector<int> pre;
        Help(){ visit = 0; num = 1; length = INF; }
};
class MGraph                //矩阵图 
{
    public:
        int n;
        int **matrix;
        MGraph(){ matrix = NULL; }
};
class Node              //链式图 
{
    public:
        int n;
        int ew;
        Node(int tn, int tw){ n = tn; ew = tw; }
};
class LGraph
{
    public:
        vector<Node> *vs;
        int n;
        LGraph(){ vs = NULL; }
};
MGraph* create_mGraph()
{
    int i, from, to, w, vn, en;     //点数、边数 
    MGraph *g = new MGraph();
    scanf("%d%d", &vn, &en);
    g->n = vn;
    g->matrix = new int*[vn];
    for(i = 0; i < vn; i++)
    {
        g->matrix[i] = new int[vn];
        fill(g->matrix[i], g->matrix[i] + vn, INF);
        g->matrix[i][i] = 0; 
    }
    for(i = 0; i < en; i++)
    {
        cin >> from >> to >> w;
        g->matrix[from][to] = w;    
        //无向图修改成: g->matrix[from][to] = g->matrix[to][from] = w;    
    }
    return g;
}
LGraph *create_lGraph()
{
    int i, from, to, w, vn, en;     //点数、边数 
    LGraph *g = new LGraph();
    scanf("%d%d", &vn, &en);
    g->n = vn;
    g->vs = new vector<Node>[vn];
    for(i = 0; i < en; i++)
    {
        cin >> from >> to >> w;
        Node *temp = new Node(to, w);
        g->vs[from].push_back(*temp);
        //无向图加上:Node temp(from, w);  g->vs[to].push_back(temp);
    }
    return g;
}
//矩阵图的dijkstra算法实现 
Help *dijkstra_mGraph(int s, int v, MGraph *g)
{
    int i, j, vn = g->n;
    Help *h = new Help[vn];
    h[s].length = 0;
    for(i = 0; i < vn; i++)
    {
        int cur = -1, min = INF;
        for(j = 0; j < vn; j++)     //时间复杂度vn的平方 
            if(h[j].length < min && !h[j].visit)
                min = h[cur = j].length;
        if(cur == v)        //如果需要判断是否有路,在这步之前判断
            return h;
        h[cur].visit = 1;    
        for(j = 0; j < vn; j++)
        {
            if(!h[j].visit && g->matrix[cur][j] != INF)
            {
                int newLen = g->matrix[cur][j] + h[cur].length;
                if(newLen < h[j].length)
                {
                    h[j].length = newLen;
                    h[j].pre.clear();
                    h[j].pre.push_back(cur);
                    h[j].num = h[cur].num;
                }else if(newLen == h[j].length){
                    h[j].pre.push_back(cur);
                    h[j].num += h[cur].num;
                }
            }
        }
    } 
}
//链式图的dijkstra算法实现 
Help *dijkstra_lGraph(int s, int v, LGraph *g)
{
    int i, j, vn = g->n;
    Help *h = new Help[vn];
    h[s].length = 0;
    for(i = 0; i < vn; i++)
    {
        int min = INF, cur = -1;
        for(j = 0; j < vn; j++)
            if(h[j].length < min && !h[j].visit)
                min = h[cur = j].length;
        h[cur].visit = 1; 
        if(cur == v)
            return h;
        for(j = 0; j < g->vs[cur].size(); j++)
        {
            Node to = g->vs[cur][j];
            int newLen = h[cur].length + to.ew;
            if(newLen < h[to.n].length)
            {
                h[to.n].length = newLen;
                h[to.n].num = h[cur].num;
                h[to.n].pre.clear();
                h[to.n].pre.push_back(cur);
            }else if(newLen == h[to.n].length){
                h[to.n].pre.push_back(cur);
                h[to.n].num += h[cur].num;
            }
        }
    }
}
int main()
{
    int s, v;
    //链式图 
    LGraph *lg = create_lGraph();
    for(int i = 0; i < lg->n; i++)
    {
        cout << i << " ";
        for(int j = 0; j < lg->vs[i].size(); j++)
            cout << lg->vs[i][j].n << " ";
        cout << endl;
    }
    cin >> s >> v;
    Help *lh = dijkstra_lGraph(s, v, lg);
    //矩阵图 
    MGraph *mg = create_mGraph();
    for(int i = 0; i < mg->n; i++)
    {
        for(int j = 0; j < mg->n; j++)
            cout << mg->matrix[i][j] << " ";
        cout << endl;
    }
    cin >> s >> v;
    Help *mh = dijkstra_mGraph(s, v, mg);
    return 0;
}
/*
    graph: 
        5 8
        0 1 10
        0 3 30
        0 4 100
        1 2 50
        2 4 10
        3 1 10
        3 2 20
        3 4 60
    s、v: 
        0 4
    dijkstra:
        0 INF INF INF INF
        0 10 INF 30 100 
        0 10 60 30 100
        0 10 50 30 90
        0 10 50 30 60
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值