洛谷P1144

最短路计数

题目描述

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

输入格式

第一行包含 \(2\) 个正整数 \(N,M\),为图的顶点数与边数。

接下来 \(M\) 行,每行 \(2\) 个正整数 \(x,y\),表示有一条由顶点 \(x\) 连向顶点 \(y\) 的边,请注意可能有自环与重边。

输出格式

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

样例 #1

样例输入 #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\to 2\to 4\to 5\)\(2\)\(1\to 3\to 4\to 5\)(由于 \(4\to 5\) 的边有 \(2\) 条)。

对于 \(20\%\) 的数据,\(1\le N \le 100\)
对于 \(60\%\) 的数据,\(1\le N \le 10^3\)
对于 \(100\%\) 的数据,\(1\le N\le10^6\)\(1\le M\le 2\times 10^6\)


1、因为边权是1所以bfs,spfa,dijkstra都可以因为spfa最近在学习所以而且spfa打起来挺顺手的,就用spfa打的

2、我们用一个数组记录每个点最短路的答案

3、这里自环和重边不要用考虑,因为前向星中存的边会跑完,重边会跑两遍,这样的话不会影响计数的,举个例子就是

1 2
1 2
1 2

这里答案会输出1 2,因为1到2有两条边会都会跑所以最短路有两条

4、我们考虑ans的更新。采用分类讨论。

if(d[j] > d[t] + 1)
            {
                d[j] = d[t] + 1;
                ans[j] = ans[t] % mod;
                if(!inq[j])
                {
                    inq[j] = 1;
                    q.push(j);
                }
            }
            else if(d[j] == d[t] + 1)    
            ans[j] =(ans[j] + ans[t]) % mod;

5、注意答案要边计算边取模

6、注意要初始化链表啊,表头最开始全部初始化为 -1


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

using namespace std;

const int N = 1e6 + 10, M = 2e6 + 10, mod = 100003;

int n, m, ans[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 ++;
}

int d[N];
bool inq[N];
void spfa()
{
    queue<int> q;
    for(int i = 1; i <= n; ++ i)    d[i] = 0x7fffffff;
    memset(inq, 0, sizeof inq);
    d[1] = 0; q.push(1); inq[1] = 1; ans[1] = 1;
    while(q.size())
    {
        auto t = q.front(); q.pop(); inq[t] = 0;
        for(int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(d[j] > d[t] + 1)
            {
                d[j] = d[t] + 1;
                ans[j] = ans[t] % mod;
                if(!inq[j])
                {
                    inq[j] = 1;
                    q.push(j);
                }
            }
            else if(d[j] == d[t] + 1)    
            ans[j] =(ans[j] + ans[t]) % mod;
        }
    } 
}
int main()
{
    freopen("1.txt","r",stdin);
    memset(h, -1, sizeof h);
    cin >> n >> m;
    for(int i = 1; i <= m; ++ i)
    {
        int a, b; cin >> a >> b;
        add(a, b);add(b, a);
    }
    spfa();
    for(int i = 1; i <= n; ++ i)    cout << ans[i] << endl;
    return 0;
}
posted @ 2022-11-01 16:35  cxy8  阅读(18)  评论(0编辑  收藏  举报