最短路计数_SPFA

P1144 最短路计数 传送门

题目描述
给出一个 NN 个顶点 MM 条边的无向无权图,顶点编号为 1-N1−N 。问从顶点 11 开始,到其他每个点的最短路有几条。
输入输出格式
输入格式:
第一行包含 22 个正整数 N,MN,M ,为图的顶点数与边数。

接下来 MM 行,每行 22 个正整数 x,yx,y ,表示有一条顶点 xx 连向顶点 yy 的边,请注意可能有自环与重边。

输出格式:
共 NN 行,每行一个非负整数,第 ii 行输出从顶点 11 到顶点 ii 有多少条不同的最短路,由于答案有可能会很大,你只需要输出 ans \bmod 100003ansmod100003 后的结果即可。如果无法到达顶点 ii 则输出 00 。
输入输出样例
输入样例#1:
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
输出样例#1:
1
1
1
2
4

差不多是SPFA的模板题了吧. 看这庞大的数据范围, 就知道Dijkstra是不可能的了. 而SPFA的时间复杂度是O(kE), k是常数, E是边的数量.

不得不说在边少的情况SPFA还真是优秀啊.

需要注意的一点是最短路计数

怎么记呢? 只需要在判断长度的代码那里稍微改动一点即可.

两种情况

  1. 如果长度可以更新, 那么就更新, 且把u点的结果数count赋值到v点上
  2. 如果长度和原来一样, 说明从两种路走来的情况都是最短路, 那么count[v] 就要加上count[u].

除此以外没什么特殊的了. 重边不重边什么的都OK的啦

#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

const int maxn = 1000005;
const int INF = 0x3f3f3f3f;
const int mode = 100003;
bool in[maxn] = {};
int n, m, dis[maxn], count[maxn] = {};
vector<int> G[maxn];

void spfa()
{
    dis[1] = 0;
    queue<int> que;
    que.push(1);
    in[1] = true;
    count[1] = 1;
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        in[u] = false;
        for (int i = 0; i < G[u].size(); ++i) {
            int v = G[u][i];
            //cout << "out u = " << u << "  v = " << v << endl;
            //cout << "dis[u] = " << dis[u] << "  dis[v] = " << dis[v] << endl;
            if (dis[v] > dis[u] + 1) {
                //cout << "v = " << v << endl;
                dis[v] = dis[u] + 1; // 靠, 这里写错了 
                count[v] = count[u];
                if (!in[v]) {
                    que.push(v);
                    in[v] = true;
                }
            } else if (dis[u] + 1 == dis[v]) {
                //cout << "u = " << u << "  v = " << v << endl;
                count[v] += count[u];
                count[v] %= mode;
                if (!in[v]) {
                    que.push(v);
                    in[v] = true;
                }
            }
        }
    }
}

int main()
{
    memset(dis, 0x3f, sizeof(dis));
    cin >> n >> m;
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    spfa();
    for (int i = 1; i <= n; ++i) {
        cout << count[i] << '\n';
    }
}
/*
数据这么大, 看来非spfa不可了 
*/
/*
5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5
*/

最后

以及博客100祭 hiehie

猜你喜欢

转载自blog.csdn.net/wjh2622075127/article/details/81260166
今日推荐