洛谷P1144《最短路计数》

原更新日期:2019-01-12 09:57:14

最短路“板子”

题目描述

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

输入输出格式

输入格式

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

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

输出格式

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

输入输出样例

输入样例

5 7
1 2
1 3
2 4
3 4
2 3
4 5
4 5

输出样例

1
1
1
2
4

说明

\(1\)\(5\)的最短路有\(4\)条,分别为\(2\)\(1-2-4-5\)\(2\)\(1-3-4-5\)(由于\(4−5\)的边有\(2\)条)。

对于\(20\%\)的数据,\(N ≤ 100\)

对于\(60\%\)的数据,\(N ≤ 1000\)

对于\(100\%\)的数据,\(N<=1000000,M<=2000000\)

解题思路

稍微改一下最短路板子即可

具体就是用 ans[i] 数组记录一下到i点的最短路个数,在更新路径长度的时候判一下两条路径长度的关系即可

const int HA = 100006;

/* ... */

for (int e = head[now]; e; e = edge[e].next) {
    int to = edge[e].now;
    if (dis[to] > dis[now] + edge[e].weight) {
    // 两条路径长度不等,更新答案
        dis[to] = dis[now] + edge[e].weight;
        ans[to] = ans[now];
        q.push(NewNode(dis[to], to));
    } else if (dis[to] == dis[now] + edge[e].weight) {
    	// 两条路径长度相等,将答案相加
        ans[to] += ans[now];
        ans[to] %= HA;
    }
}

代码实现

/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>

/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>

/* -- External Headers -- */
#include <map>
#include <cmath>

/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)

namespace FastIO {
    
    inline int getint() {
        int s = 0, x = 1;
        char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') x = -1;
            ch = getchar();
        }
        while (isdigit(ch)) {
            s = s * 10 + ch - '0';
            ch = getchar();
        }
        return s * x;
    }
    inline void __basic_putint(int x) {
        if (x < 0) {
            x = -x;
            putchar('-');
        }
        if (x >= 10) __basic_putint(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void putint(int x, char external) {
        __basic_putint(x);
        putchar(external);
    }
}


namespace Solution {
    const int HA = 100003;
    
    struct Graph {
        static const int MAXN = 1000000 + 10;
        static const int MAXM = 2000000 + 10;
        
        struct Node {
            int nweight, now;
            
            Node() { nweight = now = 0; }
            
            bool operator < (const Node &that) const {
                return nweight > that.nweight;
            }
        };
        
        struct Edge {
            int now, weight, next;
        } edge[MAXM * 2];
        
        int head[MAXN], dis[MAXN], ans[MAXN], cnt;
        
        inline void addEdge(int prev, int next, int weight, bool isR = true) {
            if (isR) { addEdge(next, prev, weight, false); }
            edge[++cnt].now = next;
            edge[cnt].weight = weight;
            edge[cnt].next = head[prev];
            head[prev] = cnt;
        }
        
        inline Node NewNode(int nowWeight, int now) {
            Node tmp;
            tmp.nweight = nowWeight;
            tmp.now = now;
            return tmp;
        }
        
        inline void SPFA() {
            memset(dis, 0x7f, sizeof(dis));
            memset(ans, 0, sizeof ans);
            std::priority_queue<Node> q;
            q.push(NewNode(0, 1));
            dis[1] = 0;
            ans[1] = 1;
            while (!q.empty()) {
                Node NowNode = q.top();
                q.pop();
                int now = NowNode.now;
                for (int e = head[now]; e; e = edge[e].next) {
                    int to = edge[e].now;
                    if (dis[to] > dis[now] + edge[e].weight) {
                        dis[to] = dis[now] + edge[e].weight;
                        ans[to] = ans[now];
                        q.push(NewNode(dis[to], to));
                    } else if (dis[to] == dis[now] + edge[e].weight) {
                        ans[to] += ans[now];
                        ans[to] %= HA;
                    }
                }
            }
        }
    } g1;
    
    int n, m;
}

signed main() {
#define HANDWER_FILE
#ifndef HANDWER_FILE
    freopen("testdata.in", "r", stdin);
    freopen("testdata.out", "w", stdout);
#endif
    using namespace Solution;
    using FastIO::getint;
    n = getint();
    m = getint();
    For (i, 1, m) {
        int prev = getint();
        int next = getint();
        g1.addEdge(prev, next, 1);
    }
    g1.SPFA();
    For (i, 1, n) {
        FastIO::putint(g1.ans[i], '\n');
    }
    return 0;
}


posted @ 2020-10-14 18:29  Handwer  阅读(41)  评论(0编辑  收藏  举报