洛谷 P1144 最短路计数 题解

这道题的目的是要求出每个点的单源最短路数量。

那么对于每个点,我们需要知道其距离起点的距离和当前搜到的最短路的条数,分别用数组 dis [ i ] 和 f [ i ] 来表示。

从而,我们选择用广搜来进行实现(一是边权为恒为1,二是保证第一次搜到的 dis [ i ] 即为最短的)

对于每一个新搜到的点,操作为更新距离和更新最短路条数(等于上一个节点的最短路条数,因为是第一次搜到)。

对于每一个搜到过的点,如果其距离等于最短路距离,则将其最短路条数加上上一个节点的最短路条数。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 2000010
#define int long long
#define rep(i,s,e) for(register int i=s;i<=e;++i)
#define dwn(i,s,e) for(register int i=s;i>=e;--i)
using namespace std;
inline int read()
{
    int x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0'; c=getchar();}
    return f*x;
}
inline void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
int n,m,cnt;
int head[maxn];
int dis[maxn],f[maxn];
struct node
{
    int v,nex;
}edge[maxn];
inline void add(int x,int y)
{
    edge[++cnt].v=y;
    edge[cnt].nex=head[x];
    head[x]=cnt;
}
signed main()
{
    n=read();m=read();
    rep(i,1,m)
    {
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dis[1]=0;f[1]=1;
    rep(i,2,n) dis[i]=(1<<30);
    queue<int> q;
    q.push(1);
    while(!q.empty())
    {
        int from=q.front();
        q.pop();
        for(int i=head[from];i;i=edge[i].nex)
        {
            int to=edge[i].v;
            if(dis[to]==(1<<30))
            {
                dis[to]=dis[from]+1;
                f[to]=f[from];
                q.push(to);
            }
            else 
                if(dis[to]==dis[from]+1)
                    f[to]=(f[to]+f[from])%100003;
        }
    }
    rep(i,1,n) cout<<f[i]<<endl;
    return 0;
}

 

posted @ 2020-09-06 21:52  handsome_zyc  阅读(180)  评论(1编辑  收藏  举报