LuoguP1144 最短路计数 解题报告【SPFA/BFS】

来源:互联网 发布:淘宝波奇网有假货吗 编辑:程序博客网 时间:2024/06/07 06:00

题目描述
给出一个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,然而这里叫我们求最短路条数我们就要在dis数组上做文章。具体地,如果v这个点可以被u松弛,那么v的最短路条数就等于u的最短路条数。如果v这个点已经求出的最短路长度和u相等,那么v的最短路条数就要加上u的。
然而问题是这道题的边没有边权,我们用朴素的BFS就可以解决这个问题(在BFS树中的深度)。
代码如下:

#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=1000000,M=2000000,mod=100003;struct edge{    int v,w,next;}ed[2*M+5];int n,m;int head[N+5],num;int dis[N+5],flag[N+5],ans[N+5];void build(int u,int v,int w){    ed[++num].v=v;    ed[num].w=w;    ed[num].next=head[u];    head[u]=num;}void SPFA(){    queue<int>q;    memset(dis,0x3f,sizeof(dis));    memset(flag,0,sizeof(flag));    memset(ans,0,sizeof(ans));    flag[1]=1,dis[1]=0,ans[1]=1;    q.push(1);    while(!q.empty())    {        int u=q.front();q.pop();        flag[u]=0;        for(int i=head[u];i!=-1;i=ed[i].next)        {            int v=ed[i].v;            if(dis[v]>dis[u]+ed[i].w)            {                dis[v]=dis[u]+ed[i].w;                ans[v]=ans[u];                if(!flag[v])                {                    q.push(v);                    flag[v]=1;                }            }            else if(dis[v]==dis[u]+ed[i].w)ans[v]=(ans[v]%mod+ans[u]%mod)%mod;        }    }}int main(){    memset(head,-1,sizeof(head));    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int u,v;        scanf("%d%d",&u,&v);        build(u,v,1);        build(v,u,1);    }    SPFA();    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);    return 0;}
原创粉丝点击