Magical Girl Haze 计蒜客 分层最短路(dp + 最短路)

Magical Girl Haze

思路:

分层最短路的实质是dp思想 + 最短路。

在跑最短路的过程中,我们可以选择将某一条边的代价变成零,但是最多只能使用k次

dis[i][j]表示到达点i使用j次免费机会的最小代价

这样就有状态转移方程 dp[i][j] = min(dp[from][j] + val(from , i) , dp[from][j - 1]);

因此我们再进行松弛操作的时候就有

if(dis[i][j] + val(i , to) < dis[to][j]) dis[to][j] = dis[i][j] + val(i , to);

if(dis[j][j] < dis[to][j + 1] && j < k) dis[to][j + 1] = dis[i][j];

AC代码:

  1 #include<cstdio>
  2 #include<string.h>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<iostream>
  6 #include<vector>
  7 #include<queue>
  8 #include<set>
  9 #include<map>
 10 #include<cctype>
 11 #define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
 12 #define mem(a,x) memset(a,x,sizeof(a))
 13 #define lson rt<<1,l,mid
 14 #define rson rt<<1|1,mid + 1,r
 15 #define P pair<int,int>
 16 #define ull unsigned long long
 17 using namespace std;
 18 typedef long long ll;
 19 const int maxn = 1e6 + 10;
 20 const ll mod = 998244353;
 21 const int inf = 0x3f3f3f3f;
 22 const long long INF = 0x3f3f3f3f3f3f3f3f;
 23 const double eps = 1e-7;
 24 inline ll read()
 25 {
 26     ll X = 0, w = 0; char ch = 0;
 27     while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
 28     while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
 29     return w ? -X : X;
 30 }
 31 int n, m, k;
 32 
 33 struct Edge {
 34     ll to, val, next;
 35 }edge[maxn];
 36 int cnt = 0;
 37 int head[maxn];
 38 void add(int u, int v, int val)
 39 {
 40     edge[++cnt].to = v, edge[cnt].val = val, edge[cnt].next = head[u], head[u] = cnt;
 41 }
 42 struct node
 43 {
 44     ll index, dist, j;
 45     bool operator < (const node& x) const
 46     {
 47         return dist > x.dist;
 48     }
 49 };
 50 ll dis[maxn][11];
 51 ll vis[maxn][11];
 52 void init()
 53 {
 54     for (int i = 0; i < maxn; ++i)
 55     {
 56         for (int j = 0; j <= k; ++j)
 57         {
 58             dis[i][j] = INF, vis[i][j] = 0;
 59         }
 60     }
 61 }
 62 inline void Dj(int s)
 63 {
 64     dis[s][0] = 0;
 65     priority_queue<node>que;
 66     que.push(node{ s , 0 , 0 });
 67     while (que.size())
 68     {
 69         node tmp = que.top(); que.pop();
 70         ll from = tmp.index;
 71         ll dist = tmp.dist;
 72         ll j = tmp.j;
 73         if (vis[from][j]) continue;
 74         vis[from][j] = 1;
 75         for (int i = head[from]; i != -1; i = edge[i].next)
 76         {
 77             ll to = edge[i].to;
 78             if (dis[from][j] + edge[i].val < dis[to][j])
 79             {
 80                 dis[to][j] = dis[from][j] + edge[i].val;
 81                 que.push(node{ to , dis[to][j] , j });
 82             }
 83             if (j < k && dis[from][j] < dis[to][j + 1])
 84             {
 85                 dis[to][j + 1] = dis[from][j];
 86                 que.push(node{ to , dis[to][j + 1] , j + 1 });
 87             }
 88         }
 89     }
 90 
 91 }
 92 
 93 
 94 int main()
 95 {
 96     int T;
 97     T = read();
 98     while (T--)
 99     {
100         mem(head, -1);
101         ll ans = INF;
102         n = read(), m = read(), k = read();
103         for (int i = 1; i <= m; ++i)
104         {
105             int u = read(), v = read(), val = read();
106             add(u, v, val);
107         }
108         init();
109         Dj(1);
110         for (int i = 0; i <= k; ++i)
111         {
112             ans = min(ans, dis[n][i]);
113         }
114         cout << ans << endl;
115     }
116 
117     return 0;
118 }
119 
120 /*
121 样例输入:
122 1
123 5 6 1
124 1 2 2
125 1 3 4
126 2 4 3
127 3 4 1
128 3 5 6
129 4 5 2
130 样例输出:
131 3
132 */
分层最短路
原文地址:https://www.cnblogs.com/DreamACMer/p/12688456.html