洛谷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  阅读(64)  评论(0)    收藏  举报