zoukankan      html  css  js  c++  java
  • #10072. 「一本通 3.2 例 1」Sightseeing Trip(floyd求最小环+路径)

    https://loj.ac/problem/10072

    针对无向图

    因为Floyd是按照结点的顺序更新最短路的,所以我们在更新最短路之前先找到一个连接点k,当前的点k肯定不存在于已存在的最短路f[i][j]的路径上,因为我们还没用这个k去更新最短路,相当于 (i -> k -> j -> j到i的最短路 -> i)这样一个环就找到了,接下来我们要记录路径,用path[i][j]表示在最短路i到j的路径上j的前一个结点,所以我们在更新最短路时也要更新这个点,原来的最短路是i -> j,现在变成了 i -> k -> j,所以有per[i][j] = pre[k][j],因为要找最小环,所以不断更新找到环的权值,环更新一次,路径也要更新一次,路径更新时根据pre数组迭代一下就ok了

    附上图片加深理解

      1 #include <bits/stdc++.h>
      2 #define read read()
      3 #define up(i,l,r) for(register int i = (l);i <= (r);i++)
      4 #define down(i,l,r) for(register int i = (l);i >= (r);i--)
      5 #define traversal_vedge(i) for(register int i = head[u]; i ;i = e[i].nxt)
      6 #define ll long long
      7 using namespace std;
      8 int read
      9 {
     10     int x = 0, f = 1; char ch = getchar();
     11     while(ch < 48 || ch > 57) {if(ch == '-')f = -1; ch = getchar();}
     12     while(ch >=48 && ch <=57) {x = 10 * x + ch - 48;ch = getchar();}
     13     return x * f; 
     14 }
     15 void write(int x)
     16 {
     17     if(x < 0) x = -x,putchar('-');
     18     if(x > 9) write(x/10);
     19     putchar(x%10 + 48);
     20 }
     21 //-------------------------------------------------
     22 const int N = 105,INF = 0xfffffff;//debug 1e9+7 -> 0xffffff//极大值要开大
     23 int n,m;
     24 int f[N][N],e[N][N],pre[N][N],path[N];
     25 //f ,e
     26 int min_ring,cnt;
     27 void init()
     28 {
     29     up(i,1,n)
     30         up(j,1,n)
     31         {
     32             f[i][j] = INF;
     33             e[i][j] = INF;
     34             pre[i][j] = i;//i -> j最短路径上j的前一个节点;
     35             //初始化; 
     36         }
     37 }
     38 
     39 void readdata()
     40 {
     41     n = read; m = read;
     42     init();
     43     up(i,1,m)
     44     {
     45         int u = read,v = read, w = read;
     46         f[u][v] = f[v][u] = e[u][v] = e[v][u] = min(w,f[u][v]);
     47         //重边中取最小; 
     48     }
     49 }
     50 
     51 void floyd()
     52 {
     53     min_ring = INF; 
     54     up(k,1,n)
     55     {
     56         //求环 
     57         up(i,1,k-1)//k不在i->j上;//这里的k是与i,j相连的;
     58         {
     59             up(j,1,i-1) //无向图利用对称性//?
     60             {
     61                 if(f[i][j] + e[i][k] + e[k][j] < min_ring) 
     62                 {
     63                     min_ring = f[i][j] + e[i][k] + e[k][j];
     64                     cnt = 0;
     65                     int tmp = pre[i][j];
     66                     while(tmp != i)
     67                     {
     68                         path[++cnt] = tmp;
     69                         tmp = pre[i][tmp];
     70                     }
     71                     path[++cnt] = i;
     72                     path[++cnt] = k;
     73                     path[++cnt] = j;
     74                 }
     75             }
     76         }
     77         //------------------------ 
     78         //求最短路;//这里的k是中转点(在i->j的最短路上)
     79         up(i,1,n)
     80             up(j,1,n)
     81             {
     82                 if(f[i][k] + f[k][j] < f[i][j])
     83                 {
     84                     f[i][j] = f[i][k] + f[k][j];
     85                     //pre[i][j]表示i到j最短路径上j前面的一个点 
     86                     //所以此时i到j的最短路径上j前一个点为k到j最短路径上j的前一个点
     87                     pre[i][j] = pre[k][j];
     88                 }
     89             }
     90     } 
     91 }
     92 
     93 void write_ans()
     94 {
     95     if(min_ring == INF) printf("No solution.
    ");
     96     else up(i,1,cnt) write(path[i]),putchar(' ');
     97 }
     98 
     99 int main()
    100 {
    101     freopen("input.txt","r",stdin);
    102     readdata();
    103     floyd();
    104     write_ans();
    105     return 0;
    106 }
  • 相关阅读:
    外校培训前三节课知识集合纲要(我才不会告诉你我前两节只是单纯的忘了)
    floyd算法----牛栏
    bfs开始--马的遍历
    (DP 线性DP 递推) leetcode 64. Minimum Path Sum
    (DP 线性DP 递推) leetcode 63. Unique Paths II
    (DP 线性DP 递推) leetcode 62. Unique Paths
    (DP 背包) leetcode 198. House Robber
    (贪心 复习) leetcode 1007. Minimum Domino Rotations For Equal Row
    (贪心) leetcode 452. Minimum Number of Arrows to Burst Balloons
    (字符串 栈) leetcode 921. Minimum Add to Make Parentheses Valid
  • 原文地址:https://www.cnblogs.com/mzg1805/p/10407220.html
Copyright © 2011-2022 走看看