• 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 }
  • 相关阅读:
    go if 判断 完成随机分数的评级
    go for循环
    go 常量2
    go 常量定义和使用
    更新数据库某字段数据为流水号
    BPM设定操作超时
    BPM打印按钮
    BPM链接处理
    项目管理
    公司规划
  • 原文地址:https://www.cnblogs.com/zjp-shadow/p/7253941.html
Copyright © 2020-2023  润新知