Luogu P1144 最短路计数

题目描述

给出一个N个顶点M条边的无向无权图,顶点编号为1~N。问从顶点1开始,到其他每个点的最短路有几条。

输入输出格式

输入格式:

输入第一行包含2个正整数N,M,为图的顶点数与边数。

接下来M行,每行两个正整数x, y,表示有一条顶点x连向顶点y的边,请注意可能有自环与重边。

输出格式:

输出包括N行,每行一个非负整数,第i行输出从顶点1到顶点i有多少条不同的最短路,由于答案有可能会很大,你只需要输出mod 100003后的结果即可。如果无法到达顶点i则输出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。

十分玄学的就过了。。。

//2018年4月21日20:17:14 
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 1000001;
const int M = 2000001;
const int mod = 100003;
int n, m;

int fir[N], edge_num, nxt[M], to[M], len[M];
void addEdge(int x, int y, int z){
    to[++edge_num] = y;
    len[edge_num] = z;
    nxt[edge_num] = fir[x];
    fir[x] = edge_num;    
}
int dis[N], q[N], sum[N], inq[N];
void SPFA(int A){
    int head=0, tail=1;
    for(int i=1; i<=n; i++)
        dis[i] = 1e9+7;
    dis[A] = 0;
    q[head] = A;
    inq[head] = 1;
    sum[A] = 1;
    while(head != tail){
        int x = q[head++];
        inq[x] = 0;
        if(head % mod == 0)
            head %= mod;
        for(int p=fir[x]; p; p=nxt[p])
            if(dis[to[p]] >= dis[x] + len[p]){
                if(dis[to[p]] > dis[x] + len[p]) sum[to[p]] = sum[x];
                else if(dis[to[p]] == dis[x] + len[p]){
                    sum[to[p]] = (sum[to[p]] + sum[x]) % mod;
                }
                dis[to[p]] = dis[x] + len[p];
                if(!inq[to[p]]){
                    inq[to[p]] = 1;
                    q[tail++] = to[p];
                    if(tail % mod == 0) tail %= mod;
                }
            }
        
    }
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i=1; i<=m; i++){
        int x, y;
        scanf("%d%d", &x, &y); 
        addEdge(x, y, 1);
        addEdge(y, x, 1); 
    }
    SPFA(1);
    for(int i=1; i<=n; i++)
        printf("%d
", sum[i]);
    
    return 0;
}
原文地址:https://www.cnblogs.com/sineagle/p/8903620.html