【洛谷 1144】最短路计数

题目描述

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

输入格式

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

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

输出格式

NN行,每行一个非负整数,第ii行输出从顶点11到顶点ii有多少条不同的最短路,由于答案有可能会很大,你只需要输出ans mod 100003ansmod100003后的结果即可。如果无法到达顶点ii则输出00。

输入输出样例

输入 #1
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
输出 #1
1
1
1
2
4

说明/提示

11到55的最短路有44条,分别为22条1-2-4-51245和22条1-3-4-51345(由于4-545的边有22条)。

对于20\%20%的数据,N ≤ 100N100;

对于60\%60%的数据,N ≤ 1000N1000;

对于100\%100%的数据,N<=1000000,M<=2000000N<=1000000,M<=2000000。

题解:又是一道最短路计数恩 ,好像比上一个版本要更好哦

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1000001;
const int mod=100003;
const int oo=0x3f3f3f3f;
int cnt,head[N],yxr=oo,B,E,P;
struct node{
    int to,next;
}e[N*2];
void add(int u,int v){
    e[++cnt].to=v; 
    e[cnt].next=head[u];
    head[u]=cnt;
}
int vis[N],dis[N],ans[N],n,m,u,v;
queue<int>q;
void SPFA(int s){
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    vis[s]=1; dis[s]=0; q.push(s);
    int x,v; ans[1]=1;
    while(!q.empty()){
        x=q.front(); q.pop(); vis[x]=0;
        for(int i=head[x];i;i=e[i].next){
            v=e[i].to;
            if(dis[v]>dis[x]+1){
                dis[v]=dis[x]+1;
                ans[v]=ans[x];
                if(!vis[v]) { q.push(v); vis[v]=1; }
            }
            else if(dis[v]==dis[x]+1)
                    { ans[v]+=ans[x]; ans[v]%=mod; }
            //if(dis[v]>dis[x]+1){
            //    dis[v]=dis[x]+1;
            //    if(!vis[v]) { vis[v]=1; q.push(v); }
            //} 
        }
    }
}

int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d %d",&u,&v);
        add(u,v); add(v,u);
    }
    SPFA(1); 
    for(int i=1;i<=n;i++)
        printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/wuhu-JJJ/p/11722175.html