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。

跑小改的spfa

对于某个点i,一条到达他的最短路径,必须经过一个和i直接相连而且最短路长度比i小1的点x。、

下面是丑陋的代码

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

queue<int>que;
const int N=200002;
const int mod=100003;
int dis[N];
int n,m;
int head[N];
int count[N];
int vis[N];
struct node{
    int l,next;
}edge[N*2];

int num=0;
void add_edge(int x,int y)
{
    edge[num].l=y;
    edge[num].next=head[x];
    head[x]=num++;
}

void spfa()
{
    que.push(1);
    count[1]=1;
    dis[1]=1;
    vis[1]=1;
    while(!que.empty())
    {
        int k=que.front();
        que.pop();
        for(int i=head[k];i!=-1;i=edge[i].next)
        {
            int q=edge[i].l;
            if(dis[k]+1<dis[q])
            {
                dis[q]=dis[k]+1;
                count[q]=count[k]%mod;
                if(!vis[q])
                {
                    vis[q]=1;
                    que.push(q);
                }
            }
            else if(dis[k]+1==dis[q])
            count[q]=(count[q]+count[k])%mod;
        }
        vis[k]=0;
    }
    for(int i=1;i<=n;i++)
    printf("%d
",count[i]);
}

int main()
{
    memset(dis,1,sizeof(dis));
    memset(head,-1,sizeof head);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        add_edge(a,b);
        add_edge(b,a);
    }
    spfa();
    return 0;
}
原文地址:https://www.cnblogs.com/sssy/p/6874103.html