单源最短路 Dijkstra

/*
    Dijkstra 算法求单源最短路径
    将所有结点分为两个集合 S D ,S为未访问的结点集合,D为已访问的集合
    每次从集合D中找到一条到达集合S中结点的最短路径,将该点加入到D集合,并更新加入该点后的最短路径
*/
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int MAX=1E9;
const int Size=720;
class Dist{ //存放找到的当前最短路径
public:
    int index; //结点下标
    int length; //路径长度
    int pre; //当前结点前驱下标
    friend const bool operator < (const Dist &a,const Dist &b)
    {
        return a.length>b.length;//小的优先级高,用于优先队列
    }
};
class Graph{
public:
    int numv; //结点数
    int *mark; //标记已访问结点,未访问为0
    int * *ma; //邻接矩阵
    Graph(int n)
    {
        numv=n;
        ma=(int * *)new int [n];
        for(int i=0;i<n;i++)ma[i]=new int[n];
        mark=new int [n];
    }
};
void Dijkstra(Graph &G,int s,Dist* &D) //s为源点
{
    using std::priority_queue;
    D=new Dist[G.numv];
    for(int i=0;i<G.numv;i++) //Dist初始化
    {
        G.mark[i]=0;
        D[i].index=i;
        D[i].length=MAX; //Dist存放长度为极大值,若算法结束后仍为极大值认为未找到可达路径
        D[i].pre=s;
    }
    D[s].length=0;
    priority_queue<Dist> H; //优先队列,存放最短路径
    H.push(D[s]);
    for(int i=0;i<G.numv;i++)
    {
        bool f=false;
        Dist d;
        while(!H.empty())
        {
            d=H.top();
            H.pop();
            if(G.mark[d.index]==0) //寻找未访问结点
            {
                f=true;
                break;
            }
        }
        if(!f)break; //未找到可访问结点退出
        int v=d.index; //v找到的当前结点
        G.mark[v]=1; //标记v为已访问
        for(int i=0;i<G.numv;i++)
        {
            if(G.ma[v][i]>0) //访问v的边,i为目标点
            {
                if(D[i].length>(D[v].length+G.ma[v][i])) //若经过v的某条边,使得s到i的距离比Dist中存放的最短路更短
                {
                    D[i].length=D[v].length+G.ma[v][i]; //更新Dist[i](s到i的最短路)
                    D[i].pre=v; //改变到i的最短路前驱为v
                    H.push(D[i]); //将新的最短路放入优先队列
                }
            }
        }
    }
}
int main()
{
    int n;cout <<"d"<<endl;
    int a,b,c,e;
    Dist *d;
    Graph g(100);
    while(cin>>n)
    {
        g.numv=n+1;
        for(int i=0;i<=n;i++)g.mark[i]=0;
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                g.ma[i][j]=0;
        while(cin>>a>>b)
        {
            if(a==-1&&b==-1)break;
            cin >> c;
            g.ma[a][b]=c;
        }
        cin>>e;
        Dijkstra(g,e,d);
        for(int i=1;i<n+1;i++)
            cout << d[i].index << " " <<d[i].length <<" "<<d[i].pre<<endl;

    }
    return 0;
}
/*
3
1 2 8
1 3 3
3 2 3
-1 -1
1
5
1 4 30
1 2 10
1 5 100
2 3 50
3 5 10
4 5 60
4 2 10
4 3 20
-1 -1
1
6
1 3 15
2 1 10
2 4 2
2 6 30
4 2 20
4 5 15
5 2 4
6 3 4
6 5 10
6 1 10
-1 -1
2
*/

猜你喜欢

转载自www.cnblogs.com/LowBee/p/9049958.html
今日推荐