1. 程式人生 > >最短路(SPFA)

最短路(SPFA)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define M 10005
#define INF 88888888
struct edge
{
    int to,w;//儲存邊的資訊,包括邊的終點以及權值
};
long long dis[M];  //最短距離的估計值(當前該點的最短距離)
bool inq[M]; //標記該點是否在佇列之中
vector<edge> g[M]; //利用一個vector儲存,g[i]表示以i為起點的所有邊的資訊
int n,m,ee;
void spfa(int u)
{
    for(int i = 0;i <= n;i++) //初始化
    {
        dis[i] = INF; //將估計值都初始化為INF
        inq[i] = false; //初始化為不在佇列中
    }
    dis[u] = 0; //起點的估計值直接就是0
    inq[u] = true; //加入佇列並進行標記
    queue<int> q;
    q.push(u);
    while(!q.empty())
    {
        u = q.front();
        inq[u] = false;
        q.pop();
        for(int i = 0;i < g[u].size();i++)
        {
            int v = g[u][i].to; //找出這條邊對應的終點
            int w = g[u][i].w;  //這條邊對應的權值
            if(dis[v] > dis[u]+w) //如果終點的最短距離比起點的最短距離加上這條邊的權值那麼就更新
            {
                dis[v] = dis[u]+w;
                if(!inq[v]) //如果v點的最短距離有所更新並且不在佇列中,就將其加入佇列。
                {           //否則就不需要重複加入佇列增加不必要的操作。
                    inq[v] = true;  //加入佇列並標記
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    while(scanf("%d %d %d",&n,&m,&ee)==3)
    {
        for(int i = 0;i <= n;i++) //清空vector避免多kase相互影響
            g[i].clear();
        for(int i = 0;i < m;i++)
        {
            int a,b,c;
            scanf("%d %d %d",&a,&b,&c);
            edge e;
            e.to = b;e.w = c;
            g[a].push_back(e);
            //e.to = a;
            //g[b].push_back(e);  //題目中有說從a到b有這條路,並不是雙向的。
        }
        spfa(ee);
        for(int i = 1; i <= n; i++){
        	if(ee == i)
            	printf("0 ");
        	else{
                if(dis[i] == 88888888) {
                    cout << 2147483647 << " ";
                    continue;
                }
            	printf("%d ",dis[i]);
        	}
    	}
        cout << endl;
    }
    return 0;
}