1. 程式人生 > >2680 【多源最短路 Bellman-Fordl模板】

2680 【多源最短路 Bellman-Fordl模板】

題目描述:

One day , Kiki wants to visit one of her friends. As she is liable to carsickness , she wants to arrive at her friend’s home as soon as possible . Now give you a map of the city’s traffic route, and the stations which are near Kiki’s home so that she can take. You may suppose Kiki can change the bus at any station. Please find out the least time Kiki needs to spend. To make it easy, if the city have n bus stations ,the stations will been expressed as an integer 1,2,3…n.

Input

There are several test cases. 
Each case begins with three integers n, m and s,(n<1000,m<20000,1=<s<=n) n stands for the number of bus stations in this city and m stands for the number of directed ways between bus stations .(Maybe there are several ways between two bus stations .) s stands for the bus station that near Kiki’s friend’s home. 
Then follow m lines ,each line contains three integers p , q , t (0<t<=1000). means from station p to station q there is a way and it will costs t minutes . 
Then a line with an integer w(0<w<n), means the number of stations Kiki can take at the beginning. Then follows w integers stands for these stations. 

Output

The output contains one line for each data set : the least time Kiki needs to spend ,if it’s impossible to find such a route ,just output “-1”.

Sample Input

5 8 5
1 2 2
1 5 3
1 3 4
2 4 7
2 5 6
2 3 5
3 5 1
4 5 1
2
2 3
4 3 4
1 2 3
1 3 4
2 3 2
1
1

Sample Output

1
-1

題目大意:

給定一個無向圖,給定終點,以及多個起點,求任意起點到終點最短路徑。

解題思路:

。。

現在明白了“圖論只會套模板”是什麼意思了,我連模板都不會套,,對著Dijkstra弄了半天,以為是單源最短路,怎麼都覺得好麻煩,定睛再一看,這不是多源最短路嗎?!又去套多源最短路的模板,樣例過了,思路絕對沒問題【模板沒套錯】,然後RunTime了,,等等,RunTime,RunTime是陣列越界?改了陣列大小,三重迴圈正好TLE,WTFunny。所以模板又套錯了,看看自己寫的神仙模板Bellman-Fordl,就是spfa,恩,整理的狗屁模板啊,模板會規定好起點嗎?【心塞*3】

樣例中第一個樣例如圖:

程式碼實現:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define M 1009
#define INF 0x3f3f3f3f
struct edge
{
    int to,w;//儲存邊的資訊,包括邊的終點以及權值
};
int 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有這條路,並不是雙向的。
        }
        int s;
        scanf("%d",&s);
        for(int i = 0;i < s;i++)
        {
            int a;
            scanf("%d",&a);
            edge e;
            e.to = a; e.w = 0;
            g[0].push_back(e); //將家裡到起點的權值設為0
            //e.to = 0;
            //g[a].push_back(e);  //從起點到家裡是否有路其實無關緊要,因為思考一下有路的話 起點到起點也是0,所以根本不影響結果
        }
        spfa(0);
        //printf("debug-----%d\n",dis[ee]);
        if(dis[ee]==INF)
            printf("-1\n");
        else
            printf("%d\n",dis[ee]);
    }
    return 0;
}

果然是簡潔又通用,我得看明白講解演算法樣例和演算法模板的區別,晚安!!