1. 程式人生 > >洛谷 P1144 最短路計數 解題報告

洛谷 P1144 最短路計數 解題報告

++ 報告 CA amp ret 正整數 std 最短路 www

P1144 最短路計數

題目描述

給出一個\(N\)個頂點\(M\)條邊的無向無權圖,頂點編號為\(1-N\)。問從頂點1開始,到其他每個點的最短路有幾條。

輸入輸出格式

輸入格式:

第一行包含2個正整數\(N,M\),為圖的頂點數與邊數。

接下來\(M\)行,每行2個正整數\(x,y\),表示有一條頂點\(x\)連向頂點\(y\)的邊,請註意可能有自環與重邊。

輸出格式:

\(N\)行,每行一個非負整數,第\(i\)行輸出從頂點1到頂點\(i\)有多少條不同的最短路,由於答案有可能會很大,你只需要輸出\(ans\) \(mod\) 100003後的結果即可。如果無法到達頂點\(i\)則輸出0 。


最短路計數,這個用spfa寫的。

思路和disj是一樣的社交網絡


Code:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N=1000010;
const int mod=100003;
int head[N],to[N<<2],next[N<<2],cnt0;
void add(int u,int v)
{
    next[++cnt0]=head[u];to[cnt0]=v;head[u]=cnt0;
    next[++cnt0]=head[v];to[cnt0]=u;head[v]=cnt0;
}
int n,m,dis[N],used[N],cnt[N];
queue <int > q;
void spfa()
{
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;cnt[1]=1;
    q.push(1);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i;i=next[i])
        {
            int v=to[i];
            if(dis[v]>dis[u]+1)
            {
                 dis[v]=dis[u]+1;
                 cnt[v]=cnt[u];
                 if(!used[v])
                 {
                     used[v]=1;
                     q.push(v);
                 }
            }
            else if(dis[v]==dis[u]+1)
                cnt[v]=(cnt[v]+cnt[u])%mod;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    int u,v;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    spfa();
    for(int i=1;i<=n;i++)
        printf("%d\n",cnt[i]);
    return 0;
}

2018.7.1

洛谷 P1144 最短路計數 解題報告