zoukankan      html  css  js  c++  java
  • luogu【P1144】最短路计数

    原题入口

    这道题 一道有关于最短路的图论问题。 要求从1开始求解最短路的条数。

    这个题十分有趣,首先,跑裸的spfa(或者dijkstra)算出从1开始的最短路的长度

    再其次,计数的话,可以用记忆化搜索(相当于DAG dp)我们现在所遍历的路径长度要刚好是最短路的长度

    (这个程序中会有体现的)

    这个题我前面一直在TLE,就是没有用记忆化,暴力去找路径。(第一遍还因为没算空间MLE。。TAT

    后来优化后 时间效率挺不错。(300多ms)

    下面上代码:

     1 #include <bits/stdc++.h>
     2 #define Set(a, v) memset(a, v, sizeof(a))
     3 #define For(i, l, r) for(int i = (l); i <= (int)(r); ++i)
     4 #define Fordown(i, r, l) for(int i = (r); i >= (int)(l); --i)
     5 using namespace std;
     6 
     7 inline int read(){
     8     int x = 0, fh = 1; char ch;
     9     for(; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
    10     for(; isdigit(ch); ch = getchar()) x = (x<<1) + (x<<3) + (ch^'0');
    11     return x * fh;
    12 }
    13 
    14 const int N = 1000000, M = 2000000 << 1, inf = 0x3f3f3f3f;
    15 const int mod = 100003;
    16 
    17 struct graph {
    18     int to[M], Head[N], Next[M], val[M], e;
    19     void init() {
    20         e = 0;
    21         Set(Head, 0);
    22     }
    23     void add_edge (int u, int v, int w) {
    24         to[++e] = v;
    25         val[e] = w;
    26         Next[e] = Head[u];
    27         Head[u] = e;
    28     }
    29 };
    30 graph G;
    31 #define Travel(i, u, G) for(int i = G.Head[u]; i; i = G.Next[i])
    32 //链式前向星的存图方式,Travel是遍历,这样便于我们写多图,而且挺方便的 
    33 bool inq[N];
    34 int dis[N];
    35 void spfa() {
    36     queue<int> Q;
    37     Set(dis, inf);
    38     Q.push(1); dis[1] = 0;
    39     while (!Q.empty() ) {
    40         int now = Q.front(); Q.pop();
    41         inq[now] = false;
    42         Travel(i, now, G) {
    43             int v = G.to[i];
    44             if (dis[v] > dis[now] + G.val[i]) {
    45                 dis[v] = dis[now] + G.val[i];
    46                 if (!inq[v]) { inq[v] = true; Q.push(v); }
    47             } 
    48         }
    49     }
    50 }
    51 //裸的spfa不解释 
    52 
    53 int dp[N]; //记忆化搜索所记忆的东西(表示到这个点最短路的条数) 
    54 int dfs(int u, int deep) { //deep存储从1到这个点的深度 
    55     if (dp[u]) return dp[u]; //如果已经到过这个点直接返回条数                                                                  
    56     Travel(i, u, G) { 
    57         int v = G.to[i];
    58         if (deep - 1 == dis[v]) //如果deep-1等于之前算出来的dis(最短路径)
    59         //也就是说,当前我们所走的路径是可以走通的最短路之一
    60             dp[u] = (dp[u] + dfs(v, deep-1)) % mod; //计算路径个数,并继续向下递归
    61             //很简单的一个加法原理
    62     }
    63     return dp[u]; //最后记得返回这个值 
    64 }
    65 
    66 int main (){
    67     G.init();
    68     int n  = read(), m = read();
    69     while (m--) {
    70         int u = read(), v = read();
    71         G.add_edge(u, v, 1);
    72         G.add_edge(v, u, 1);
    73     }
    74     spfa();
    75     dp[1] = 1;
    76     For (i, 1, n)
    77         dp[i] = dfs(i, dis[i]); 
    78         //我们从每一个点向起点走回去,所以一开始的深度是当前这个点的最短路 
    79         //这样可以解释之前为什么是deep-1了 
    80     For (i, 1, n)
    81         printf ("%d
    ", dp[i]);
    82         //最后输出结果 
    83 }
  • 相关阅读:
    BFS visit tree
    Kth Largest Element in an Array 解答
    Merge k Sorted Lists 解答
    Median of Two Sorted Arrays 解答
    Maximal Square 解答
    Best Time to Buy and Sell Stock III 解答
    Best Time to Buy and Sell Stock II 解答
    Best Time to Buy and Sell Stock 解答
    Triangle 解答
    Unique Binary Search Trees II 解答
  • 原文地址:https://www.cnblogs.com/zjp-shadow/p/7253941.html
Copyright © 2011-2022 走看看