1. 程式人生 > 實用技巧 >洛谷P1144《最短路計數》

洛谷P1144《最短路計數》

原更新日期:2019-01-12 09:57:14

最短路“板子”

題目描述

給出一個\(N\)個頂點\(M\)條邊的無向無權圖,頂點編號為\(1-N\)。問從頂點\(1\)開始,到其他每個點的最短路有幾條。

輸入輸出格式

輸入格式

第一行包含\(2\)個正整數\(N,M\),為圖的頂點數與邊數。

接下來\(M\)行,每行\(2\)個正整數\(x,y\),表示有一條頂點\(x\)連向頂點\(y\)的邊,請注意可能有自環與重邊。

輸出格式

\(N\)行,每行一個非負整數,第\(i\)行輸出從頂點\(1\)到頂點\(i\)有多少條不同的最短路,由於答案有可能會很大,你只需要輸出 \(ans \bmod 100003\)

後的結果即可。如果無法到達頂點\(i\)則輸出\(0\)

輸入輸出樣例

輸入樣例

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

輸出樣例

1
1
1
2
4

說明

\(1\)\(5\)的最短路有\(4\)條,分別為\(2\)\(1-2-4-5\)\(2\)\(1-3-4-5\)(由於\(4−5\)的邊有\(2\)條)。

對於\(20\%\)的資料,\(N ≤ 100\)

對於\(60\%\)的資料,\(N ≤ 1000\)

對於\(100\%\)的資料,\(N<=1000000,M<=2000000\)

解題思路

稍微改一下最短路板子即可

具體就是用 ans[i] 陣列記錄一下到i點的最短路個數,在更新路徑長度的時候判一下兩條路徑長度的關係即可

const int HA = 100006;

/* ... */

for (int e = head[now]; e; e = edge[e].next) {
    int to = edge[e].now;
    if (dis[to] > dis[now] + edge[e].weight) {
    // 兩條路徑長度不等,更新答案
        dis[to] = dis[now] + edge[e].weight;
        ans[to] = ans[now];
        q.push(NewNode(dis[to], to));
    } else if (dis[to] == dis[now] + edge[e].weight) {
    	// 兩條路徑長度相等,將答案相加
        ans[to] += ans[now];
        ans[to] %= HA;
    }
}

程式碼實現

/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>

/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>

/* -- External Headers -- */
#include <map>
#include <cmath>

/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)

namespace FastIO {
    
    inline int getint() {
        int s = 0, x = 1;
        char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') x = -1;
            ch = getchar();
        }
        while (isdigit(ch)) {
            s = s * 10 + ch - '0';
            ch = getchar();
        }
        return s * x;
    }
    inline void __basic_putint(int x) {
        if (x < 0) {
            x = -x;
            putchar('-');
        }
        if (x >= 10) __basic_putint(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void putint(int x, char external) {
        __basic_putint(x);
        putchar(external);
    }
}


namespace Solution {
    const int HA = 100003;
    
    struct Graph {
        static const int MAXN = 1000000 + 10;
        static const int MAXM = 2000000 + 10;
        
        struct Node {
            int nweight, now;
            
            Node() { nweight = now = 0; }
            
            bool operator < (const Node &that) const {
                return nweight > that.nweight;
            }
        };
        
        struct Edge {
            int now, weight, next;
        } edge[MAXM * 2];
        
        int head[MAXN], dis[MAXN], ans[MAXN], cnt;
        
        inline void addEdge(int prev, int next, int weight, bool isR = true) {
            if (isR) { addEdge(next, prev, weight, false); }
            edge[++cnt].now = next;
            edge[cnt].weight = weight;
            edge[cnt].next = head[prev];
            head[prev] = cnt;
        }
        
        inline Node NewNode(int nowWeight, int now) {
            Node tmp;
            tmp.nweight = nowWeight;
            tmp.now = now;
            return tmp;
        }
        
        inline void SPFA() {
            memset(dis, 0x7f, sizeof(dis));
            memset(ans, 0, sizeof ans);
            std::priority_queue<Node> q;
            q.push(NewNode(0, 1));
            dis[1] = 0;
            ans[1] = 1;
            while (!q.empty()) {
                Node NowNode = q.top();
                q.pop();
                int now = NowNode.now;
                for (int e = head[now]; e; e = edge[e].next) {
                    int to = edge[e].now;
                    if (dis[to] > dis[now] + edge[e].weight) {
                        dis[to] = dis[now] + edge[e].weight;
                        ans[to] = ans[now];
                        q.push(NewNode(dis[to], to));
                    } else if (dis[to] == dis[now] + edge[e].weight) {
                        ans[to] += ans[now];
                        ans[to] %= HA;
                    }
                }
            }
        }
    } g1;
    
    int n, m;
}

signed main() {
#define HANDWER_FILE
#ifndef HANDWER_FILE
    freopen("testdata.in", "r", stdin);
    freopen("testdata.out", "w", stdout);
#endif
    using namespace Solution;
    using FastIO::getint;
    n = getint();
    m = getint();
    For (i, 1, m) {
        int prev = getint();
        int next = getint();
        g1.addEdge(prev, next, 1);
    }
    g1.SPFA();
    For (i, 1, n) {
        FastIO::putint(g1.ans[i], '\n');
    }
    return 0;
}