滑蒻稽的博客

【笔记】分层图DJ

分层图的题都很麻烦地要在 dijkstra 外面套个循环,其实可以不用。

以经典模板 [JLOI2011] 飞行路线 为例,给 DJ 的优先队列里面的点加一维状态 kf(u,k) 可以免费转移到 f(v,k+1),也可以付费转移到 f(v,k)

相当于 DJ 里面同时 k 层图都在跑,正确性显然(要是怀疑哪里有问题,套用普通 DJ 的证明就行)。复杂度 O(k(n+mlogm))

模板题代码:

#include <bits/stdc++.h>

using namespace std;
const int N = 10005;
int n, m, K, S, T, dis[N][12], vis[N][12];
vector<pair<int, int>> g[N];
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int>>, greater<tuple<int, int, int>>> q;

int main() {
  ios::sync_with_stdio(false);
  cin >> n >> m >> K >> S >> T;
  for(int i = 1, a, b, c; i <= m; i++) {
    cin >> a >> b >> c;
    g[a].emplace_back(make_pair(b, c));
    g[b].emplace_back(make_pair(a, c));
  }
  
  memset(dis, 0x3f, sizeof dis);
  dis[S][0] = 0;
  q.push(make_tuple(0, S, 0));
  while(!q.empty()) {
    auto [d, u, k] = q.top();
    q.pop();
    if(vis[u][k]) continue;
    vis[u][k] = true;
    for(auto [v, w] : g[u]) {
      if(dis[v][k] > d + w) {
        dis[v][k] = d + w;
        q.push(make_tuple(dis[v][k], v, k));
      }
      if(k < K && dis[v][k + 1] > d) {
        dis[v][k + 1] = d;
        q.push(make_tuple(dis[v][k + 1], v, k + 1));
      }
    }
  }
  int ans = 1e9;
  for(int i = 0; i <= K; i++)
    ans = min(ans, dis[T][i]);
  cout << ans << '\n';
  
	return 0;
}

其实我今天刚学分层图,再来做道题吧。

P3119 [USACO15JAN]Grass Cownoisseur G:tajran 缩点之后就可以给权值取负把求最长路转化为求最短路,DJ 的时候分 f(u,0/1)f(u,0) 只能通过走逆向边的方法转移到 f(v,1) 即可。

221103 UPD:

模拟赛爆炸了,有些分层图是 DAG,可以直接 O(n) 求最短路,不用 dijkstra 但是必须建图。

posted @   huaruoji  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示