0
点赞
收藏
分享

微信扫一扫

分层图最短路复习


分层图可以来解决在图上的决策最短路问题。

按​​P4568 [JLOI2011]飞行路线​​这个题来说。

走每条边时可以有次让这条边免费的机会。

建图的方法是,原图先建好,针对次免费的机会,每次机会新建一层图,新建的每层图与原图相同,这里层就理解为上下排列着的,然后对于原图中的的边,在每相邻两层图之间连一条的边,层间的边边权为,例如下图,为了简洁画的有向图。

分层图最短路复习_最短路_07


蓝色边就是层间的边,例如原图中有的边,在分层图中就从原图中的向下一层的建边,边权为

这样跑最短路时每垮一层图就表示用掉了一次免费的机会。

注意针对不同的题目最优策略不一定在第层图的号点,每层图都可能有最优策略,所以为了保险可以对每层图的点的值取一个最优。

这样连边会多连出很多边,所以注意计算加边数组的大小,而且每层图会多开点,还要注意计算点集大小

​​洛谷P4568 [JLOI2011]飞行路线​​​ 这个题边集是的,最多是,原图加两条边,其它层的图及层之间会加条边,每次最多加条边,所以边集要开到

每层图要多开个点,所以点集是的,注意都

下面的用了优化

#include <bits/stdc++.h>
#define
#define

using namespace std;
struct node {int next, to, w;}e[B];
int head[A], num;
void add(int fr, int to, int w) {
e[++num].next = head[fr]; e[num].to = to;
e[num].w = w; head[fr] = num;
}
int n, m, k, s, t, a, b, c, dis[A]; bool vis[A];
void spfa(int s) {
memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis);
deque<int> q; dis[s] = 0; q.push_back(s);
while (!q.empty()) {
int fr = q.front(); q.pop_front(); vis[fr] = 0;
for (int i = head[fr]; i; i = e[i].next) {
int ca = e[i].to;
if (dis[ca] > dis[fr] + e[i].w) {
dis[ca] = dis[fr] + e[i].w;
if (!vis[ca]) {
vis[ca] = 1;
if (q.empty() or dis[ca] > dis[q.front()]) q.push_back(ca);
else q.push_front(ca);
}
}
}
}
}

int main(int argc, char const *argv[]) {
cin >> n >> m >> k >> s >> t;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
add(a, b, c); add(b, a, c);
for (int j = 1; j <= k; j++) {
add(a + (j - 1) * n, b + j * n, 0);
add(b + (j - 1) * n, a + j * n, 0);
add(a + j * n, b + j * n, c);
add(b + j * n, a + j * n, c);
}
}
spfa(s);
for (int i = 0; i <= k; i++) ans = min(ans, dis[t + n * i]);
cout << ans << endl;
}


举报

相关推荐

0 条评论