1. 程式人生 > >luogu 1144 最短路計數 (堆優化Dijkstra)

luogu 1144 最短路計數 (堆優化Dijkstra)

題目描述

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

輸入輸出格式

輸入格式:

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

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

 

輸出格式:

共N行,每行一個非負整數,第ii行輸出從頂點1到頂點i有多少條不同的最短路,由於答案有可能會很大,你只需要輸出ans mod 100003後的結果即可。如果無法到達頂點ii則輸出0。

 

輸入輸出樣例

輸入樣例#1:

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

輸出樣例#1:

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。

題目連結:https://www.luogu.org/problemnew/show/P1144

題目分析:由於用鏈式前向星存邊,對重邊無需做特殊判斷

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
using namespace std;
int const MAXN = 1000005;
int const MAXM = 2000005;
int const INF = 0x3ffffff;
int const MOD = 100003;
int n, m, dis[MAXN], num[MAXN];
int cnt, head[MAXN];
bool vis[MAXN];
map<pair<int, int>, int> mp;
map<pair<int, int>, int>:: iterator it;

struct EDGE {
    int to, w, nxt;
}e[MAXM << 1];

void Init() {
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(vis, false, sizeof(vis));
}

void Add(int u, int v) {
    e[cnt].to = v;
    e[cnt].w = 1;
    e[cnt].nxt = head[u];
    head[u] = cnt++;
}

void HeapDijkstra(int v0) {
    priority_queue< pair<int, int>, vector< pair<int, int> >, greater< pair<int, int> > > q;
    for (int i = 1; i <= n; i++) {
        dis[i] = INF;
    }
    dis[v0] = 0;
    num[v0] = 1;
    q.push(make_pair(0, v0));
    while (!q.empty()) {
        int u = q.top().second;
        q.pop();
        if (!vis[u]) {
            vis[u] = true;
            for (int i = head[u]; i != -1; i = e[i].nxt) {
                int v = e[i].to;
                if (dis[v] == dis[u] + e[i].w) {
                    num[v] += num[u];
                    num[v] %= MOD;
                } else if (dis[v] > dis[u] + e[i].w) {
                    dis[v] = dis[u] + e[i].w;
                    q.push(make_pair(dis[v], v));
                    num[v] = num[u];
                }
            }
        }
    }
}

int main() {
    Init();
    scanf("%d %d", &n, &m);
    int u, v;
    for (int i = 0; i < m; i++) {
        scanf("%d %d", &u, &v);
        if (u == v) {
            continue;
        }
        Add(u, v);
        Add(v, u);
    }

    HeapDijkstra(1);
    for (int i = 1; i <= n; i++) {
        printf("%d\n", num[i] % MOD);
    }
}