问题 M: 最短路计数

时间限制: 1 Sec  内存限制: 128 MB
提交: 25  解决: 8
[提交] [状态] [命题人:admin]

题目描述

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

 

输入

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

 

输出

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

 

样例输入

复制样例数据

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

样例输出

1
1
1
2
4

 

提示

1到5的最短路有4条,分别为2条1→2→4→5和2条1→3→4→5(由于4→5的边有2条)。
对于100%的数据,1≤N≤100000,0≤M≤200000。


题目思路:我们根据判断最短路的松弛条件去做即可,如果当前dis[e]>dis[u]+w 那么说明曾经没有最短路,现在新的成为最短路.dp[e]=dp[u] 否则如果相等dp[e]+=dp[u] 找出这个方程之后 用spfa 或者djikstra都可以跑

AC:

#include <bits/stdc++.h>
#include <string>
#pragma GCC optimize(2)
typedef long long ll;
typedef unsigned long long ull;
const int mod=998244353;
const int maxn=1e6+5;
const ll INF=10000000000000005;
using namespace std;
ll n,m,p;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll dp[maxn];
ll dis[maxn];
int vis[maxn];
struct node{
    int e,next;
    ll w;
}edge[maxn];
int head[maxn];
ll cnt=0;
void addedge(int u,int v,int w)
{
    edge[cnt]=node{v,head[u],w};
    head[u]=cnt++;
}
struct N{
    int id;
    ll w;
    bool friend operator<(N a,N b)
    {
        return a.w>b.w;
    }
};
void dijstra()
{
    memset(vis,false,sizeof(vis));
    for(int i=1;i<=n;i++) dis[i]=INF,dp[i]=0;
    dis[1]=0;
    dp[1]=1;
    N s;s.id=1;s.w=0;
    priority_queue<N>q;
    q.push(s);
    while(1)
    {
        if(q.empty()) break;
        N u=q.top();q.pop();
        if(dis[u.id]!=u.w) continue;
        for(int i=head[u.id];~i;i=edge[i].next)
        {
            int e=edge[i].e;
            if(dis[e]>=u.w+edge[i].w)
            {
                if(dis[e]>u.w+edge[i].w)
                {
                    dp[e]=dp[u.id];
                    dis[e]=u.w+edge[i].w;
                    N now;now.id=e;
                    now.w=dis[e];
                    q.push(now);
                }
                else if(dis[e]==u.w+edge[i].w)
                    dp[e]=(dp[e]+dp[u.id])%100003;
            }
        }
    }
    return;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;ll z;
        scanf("%d%d",&x,&y);
        addedge(x,y,1);
        addedge(y,x,1);

    }
    dijstra();
    for(int i=1;i<=n;i++)
        printf("%lld\n",dp[i]);
    return 0;
}