StkOvflow

STACK OVERFLOW!

一言(ヒトコト)

你不是一个人
——lmh

AcWing1134/洛谷P1144 最短路计数

AcWing传送门
洛谷传送门

题目大意

给一个无向图,边权都是1,求出以1为源点,到各个点(1n)的最短路数量

解题思路

边权都是1的图中最短路,我们选择用BFS解决这个问题
对于每个点j,我们进行以下讨论:(假设这个j在这轮BFS中由i点转移而来)
1.dist j<dist i+1的时候,由于队列的性质,1j的若干条最短路中i,所以我们可以直接忽视这种情况
2.dist jdist i+1的时候,我们继续分成两类

a.   dist j=dist i+1
在这种情况下,代表着i可以是1j的最短路中的一个点,但是还有其它点,这里根据 加法原理 就可以得出我们cnt j应该加上cnt i(因为从1i的任意一条最短路,再加上ij这条边,都属于1j的最短路)。
b.   dist j=dist i+1
在这种情况下,代表i是目前第一个可以更新j的点,所以j是第一次被更新,需要入队,其它的操作和分类a都是一样的

代码

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

const int N = 1e5 + 10, M = N << 2, mod = 1e5 + 3;
int dist[N], n, m, cnt[N];
int h[N], e[M], ne[M], idx;

void add(int a, int b) 
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void bfs() 
{
    memset(dist, 0x3f, sizeof dist);
    queue <int> q;
    
    dist[1] = 0, cnt[1] = 1, q.push(1);
    
    while (q.size()) 
    {
        auto t = q.front(); q.pop();
        
        for (int i = h[t]; ~i; i = ne[i]) 
        {
            int j = e[i];
            if (dist[j] > dist[t] + 1)
            {
                dist[j] = dist[t] + 1;
                cnt[j] = cnt[t];
                q.push(j);
            }
            else if (dist[j] == dist[t] + 1) 
                cnt[j] = (cnt[j] + cnt[t]) % mod;
        }
    }
}

int main() 
{
    scanf("%d%d", &n, &m);
    
    memset(h, -1, sizeof h);
    while (m -- ) 
    {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v), add(v, u);
    }
    
    bfs();
    
    for (int i = 1; i <= n; i ++ ) 
        printf("%d\n", cnt[i]);
    
    return 0;
}

posted @   StkOvflow  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示