2013-05-27 21:16:15Morris

[UVA][spfa][次短路徑]

Always Late

Ajmat: Have you noticed one member of team 13 comes late in almost every contest?
Nejhum:   You mean the team of Mahbub, Moazzem and Yeamin? What's the problem with them?
Ajmat: All of them lives far away from BUET, and they always avoid the shortest path to BUET.
Nejhum: Are you kidding? Why would they do so? A computer science student won't ever do that.
Ajmat: They always avoids the shortest path. They believe that they always face the worst traffic jam on their shortest way to BUET.
Nejhum: That sounds crazy!
Ajmat: They are more crazy than you think they are. They always try to use the path whose length is smaller than or equal to that of any path to BUET except the shortest one. And for that, they sometimes visit the same junction more than once.
Nejhum: But they are not using the longest path. Then why are they late almost everyday?
Ajmat: That's because they have to spend a lot of time to find out which of the paths meet their criteria. Perhaps they don't know how to find out the second-shortest path.
Nejhum: I think we should solve this real problem in today's contest, instead of solving imaginary ones.
Ajmat: Let's try.

Input

The first line of each test case contains two integers: n (the number of junctions, 1 < n < 100) and r (the number of bi-directional roads connecting these junctions). The junctions are numbered with 0, 1, ..., n-1. Each of the next r lines (one for each road) contains three integers: two junction-numbers that the corresponding road connects and the length of the road in kilometers. The next line contains an integer q, the number of queries. Each of the next q lines contains two junction-numbers. There is a blank line after the q queries. There is at most 1 road between each junction pair. A road always connects two different junctions. Length of a road is not less than 1km and not more than 100km.
 
Input is terminated by EOF.
 

Output

For each set of output, print the set # (1, 2, � ) followed by q lines, one for each query, each containing the length of the second-shortest path between the corresponding junctions. However, for the unsolvable queries, print a '?'.
 

Sample Input

4 3
0 1 12
0 2 20
1 2 15
3
0 1
0 2
0 3

4 3
0 1 11
0 2 20
1 2 15
3
0 1
0 2
0 3

Sample Output

Set #1
35
27
?
Set #2
33
26
?

Mustaq Ahmed. 12-07-2002.

使用 spfa 更新的方式,對於每個節點記錄兩個路徑距離,分別記錄最短跟次短。

記得更新的時候,不可以將相同的值變成最短與次短。

#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
struct edge {
    int to, v;
    edge(int a, int b):
        to(a), v(b) {}
};
vector<edge> g[105];
#define oo 0xfffffff
void spfa(int st, int ed, int n) {
    int dis[105][2], inq[105] = {};
    int i, tn, tmp;
    for(i = 0; i < n; i++)
        dis[i][0] = dis[i][1] = oo;
    dis[st][0] = 0;
    queue<int> Q;
    Q.push(st);
    while(!Q.empty()) {
        tn = Q.front(), Q.pop();
        inq[tn] = 0;
        if(dis[tn][0] >= dis[ed][1])
            continue;
        for(vector<edge>::iterator it = g[tn].begin();
            it != g[tn].end(); it++) {
            tmp = dis[tn][0] + it->v;
            if(tmp == dis[it->to][0] || tmp == dis[it->to][1])
                {}
            else {
                if(dis[it->to][1] > tmp) {
                    dis[it->to][1] = tmp;
                    if(inq[it->to] == 0) {
                        inq[it->to] = 1;
                        Q.push(it->to);
                    }
                    if(dis[it->to][1] < dis[it->to][0])
                        swap(dis[it->to][0], dis[it->to][1]);
                }
            }
            tmp = dis[tn][1] + it->v;
            if(tmp == dis[it->to][0] || tmp == dis[it->to][1])
                {}
            else {
                if(dis[it->to][1] > tmp) {
                    dis[it->to][1] = tmp;
                    if(inq[it->to] == 0) {
                        inq[it->to] = 1;
                        Q.push(it->to);
                    }
                    if(dis[it->to][1] < dis[it->to][0])
                        swap(dis[it->to][0], dis[it->to][1]);
                }
            }
        }
    }
    if(dis[ed][1] == oo)
        puts("?");
    else
        printf("%d\n", dis[ed][1]);
}
int main() {
    int n, m, q, cases = 0;
    int x, y, v, i;
    while(scanf("%d %d", &n, &m) == 2) {
        for(i = 0; i < n; i++)
            g[i].clear();
        while(m--) {
            scanf("%d %d %d", &x, &y, &v);
            g[x].push_back(edge(y, v));
            g[y].push_back(edge(x, v));
        }
        printf("Set #%d\n", ++cases);
        scanf("%d", &q);
        while(q--) {
            scanf("%d %d", &x, &y);
            spfa(x, y, n);
        }
    }
    return 0;
}