Dijkstra算法求最短路和比最短路长1的路径的数目(单源最短路径plus)

题目描述

人类和人鱼拥有共同的祖先,因为某种原因发生了分化,人鱼到了大海里生活。近年来人类对大海及生态的破坏,人鱼族的生存环境受到了严重的影响。最近某地产公司筹备一个填海计划,在附近的大海中装入了声呐系统,这极大地限制了人鱼的活动。

人鱼族的居民们为了适应环境,建立了n个聚居点(从1到n编号),m条有一定长度的单向通道,每条由一个聚居点通向另一个聚居点。人鱼族派出了美人鱼珊珊去勾引地产公司的老总刘轩,来逼迫他关闭声呐系统。现在珊珊在S号点,她要到T号点,然后通过T号点到达陆地上。她当然希望自己能走最短的路来从S到达T,不过比最短路长1的路径,她也是可以接受的。她想知道从S到T的最短路和比最短路长1的路径一共有多少条。

输入

输入数据共m+2行。

第一行两个数n,m,含义如题目所述。(1<=n<=1000,1<=m<=15000)

第2到m+1行,共m行,每行3个数a[i],b[i],c[i],表示从a[i]到b[i]有一条长度为c[i]的通道(1<=a[i],b[i]<=n,1<=c[i]<=10000,可能有重边)。

第m+2行两个数S,T,含义如题目所述。

输出

输出一个数,表示从S到T的最短路和比最短路长1的路径的数目。

#include<iostream>
#define max 10001
using namespace std;
struct edg {
    int w;
    int to;
    int next;
};
class G {
private:
    edg *edgs;
    int dis[50][2][2];
    int n, m, S, T, num;
    bool isar[50][2];

    void path() {
        int l, i, j, v, min, k, len;
        dis[S][0][0] = 0;
        for (l = 0; l < 2 * n; l++) {
            v = -1;
            min = max;
            for (j = 0; j < n; j++) {
                if (!isar[j][0] && dis[j][0][0] < min) {
                    min = dis[j][0][0];
                    v = j;
                    k = 0;
                }
                else if (!isar[j][1] && dis[j][1][0] < min) {
                    min = dis[j][1][0];
                    v = j;
                    k = 1;
                }
            }
            if (v == -1)
                break;
            isar[v][k] = true;
            for (j = v; edgs[j].next != -1; j = edgs[j].next) {
                len = edgs[j].w;
                i = edgs[j].to;
                len = len + dis[v][k][0];
                if (len < dis[i][0][0]) {
                    dis[i][1][0] = dis[i][0][0];
                    dis[i][1][1] = dis[i][0][1];
                    dis[i][0][0] = len;
                    dis[i][0][1] = dis[v][k][1];
                }
                else if (len == dis[i][0][0]) {
                    dis[i][0][1] += dis[v][k][1];
                }
                else if (len < dis[i][1][0]) {
                    dis[i][1][0] = len;
                    dis[i][1][1] = dis[v][k][1];
                }
                else if (len == dis[i][1][0]) {
                    dis[i][1][1] += dis[v][k][1];
                }
            }
        }
    }
public:
    G(int m, int n) {
        int i, j, x, y, l;
        num = n;
        this->m = m;
        this->n = n;
        edgs = new edg[m + n];
        for (i = 0; i < n; i++) {
            edgs[i].next = -1;
        }
        for (i = 0; i < m; i++) {
            cin >> x >> y >> l;
            x--, y--;
            j = x;
            while (edgs[j].next != -1) {
                j = edgs[j].next;
            }
            edgs[j].to = y;
            edgs[j].w = l;
            edgs[j].next = num;
            edgs[num++].next = -1;
            dis[i][0][0] = dis[i][1][0] = max;
            dis[i][0][1] = dis[i][1][1] = 1;
            isar[i][0] = isar[i][1] = false;
        }
        cin >> S >> T;
        S--, T--;
    }
    void ans() {
        path();
        if (dis[T][0][0] + 1 == dis[T][1][0]) {
            cout << dis[T][0][1] + dis[T][1][1] << endl;
        }
        else
            cout << dis[T][0][1] << endl;
    }
};
int main()
{
    int m, n;
    while (cin >> n >> m) {
        G *g = new G(m, n);
        (*g).ans();
        delete g;
    }
    return 0;
}
点赞