洛谷P1144最短路计数

发布于 2019-10-16  516 次阅读


题目:https://www.luogu.org/problem/P1144

题目描述

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

输入格式

第一行包含22个正整数$N,M$,为图的顶点数与边数。

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

输出格式

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

题解

我们开一个$ans$数组,记录$1$号到点到当前节点的路径个数。

所以,我们只需多加下面的代码即可:

if (dis[v] == dis[u] + 1)
    ans[v] = (ans[v] + ans[u]) % 100003;

Code

#include <algorithm>
#include <iostream>
#include <queue>
#define maxn 2000002
#define endl '\n'
#define pairs pair<int, int>
#define mod % 100003
using namespace std;

struct node
{
    int to, next;
} edge[maxn << 1];

int n, m;
int head[maxn], num;
int vis[maxn], dis[maxn];
long long ans[maxn];

inline void add_edge (int from, int to)
{
    edge[++num].next = head[from];
    edge[num].to = to;
    head[from] = num;
}

inline void dijkstra (int x)
{
    ans[x] = 1;
    for (register int i = 1; i <= n; i++) dis[i] = 2147483647;
    priority_queue<pairs> q;
    dis[x] = 0;
    q.push (make_pair (0, 1));
    while (!q.empty ())
    {
        int u = q.top ().second;
        q.pop ();
        if (vis[u]) continue;
        vis[u] = 1;
        for (register int i = head[u]; i; i = edge[i].next)
        {
            int v = edge[i].to;
            if (dis[v] > dis[u] + 1)
            {
                dis[v] = dis[u] + 1;
                q.push (make_pair (-dis[v], v));
            }
            if (dis[v] == dis[u] + 1) ans[v] = (ans[v] + ans[u])mod;
        }
    }
}

int main ()
{
    ios::sync_with_stdio (false);
    cin.tie (0);
    cout.tie (0);

    cin >> n >> m;
    for (register int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        add_edge (x, y);
        add_edge (y, x);
    }

    dijkstra (1);

    for (register int i = 1; i <= n; i++) cout << ans[i] << endl;

    return 0;
}