zoukankan      html  css  js  c++  java
  • 洛谷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 mod 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], '
    ');
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    python(三):python自动化测试定位
    python(二):用python抓取指定网页
    python(一):介绍网络爬虫
    oracle批量增加数据
    oracle数据库基本操作
    web安全测试要点
    linux下安装jdk、tomcat
    在linux上编译C
    linux基本操作
    对首次性能测试的总结与思考
  • 原文地址:https://www.cnblogs.com/handwer/p/13816502.html
Copyright © 2011-2022 走看看