分层图
重要性质
- 可以理解为有多个平行的图。
- 上一层不能到达下一层,但下一层能到达上一层。
分层图最短路
一般模型
在一个正常的图上可以进行 k次决策,对于每次决策,不影响图的结构,只影响目前的状态或代价。一般将决策前的状态和决策后的状态之间连接一条权值为决策代价的边,表示付出该代价后就可以转换状态了。
两种解法
- 建图时直接建成k+1层。
- 多开一维记录机会信息。
(视数据范围而定)
Luogu-P4568飞行路线
解法
不就是最短路减前k大的边
分层图模板
正经的dijstra
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
char c = getchar(),f = 1;x = 0;
for(;c ^ '-' && !isdigit(c);c = getchar());
if(c == '-') c = getchar(),f = -1;
for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
x *= f;
}
template<typename xxx>void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int maxn = 1010010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
struct edge{
int to,last,val;
}e[maxn<<1];
int tot,head[maxn];
inline void add(int from,int to,int val) {
++tot;
e[tot].to = to;
e[tot].val = val;
e[tot].last = head[from];
head[from] = tot;
}
int dis[maxn][12];
int vis[maxn][12];
int n,m,K;
int s,t;
struct node {
int pla,cos,kkk;
bool operator < (const node & x) const {
return cos > x.cos;
}
};
priority_queue< node >q;
inline void dj() {
for(rint i = 0;i <= n; ++i) {
for(rint j = 0;j <= K; ++j) {
dis[i][j] = inf;
vis[i][j] = 0;
}
}
q.push((node){s,0,0});dis[s][0] = 0;
while(q.size()) {
node x = q.top();
q.pop();
if(vis[x.pla][x.kkk]) continue;
vis[x.pla][x.kkk] = 1;
for(rint i = head[x.pla]; i; i = e[i].last) {
if(dis[e[i].to][x.kkk] > dis[x.pla][x.kkk] + e[i].val) {
dis[e[i].to][x.kkk] = dis[x.pla][x.kkk] + e[i].val;
q.push((node){e[i].to,dis[e[i].to][x.kkk],x.kkk});
}
if(x.kkk < K) {
if(dis[e[i].to][x.kkk + 1] > dis[x.pla][x.kkk]) {
dis[e[i].to][x.kkk + 1] = dis[x.pla][x.kkk];
q.push((node){e[i].to,dis[e[i].to][x.kkk + 1],x.kkk + 1});
}
}
}
}
return ;
}
int main()
{
read(n);read(m);read(K);
read(s);read(t);++s,++t;
for(rint i = 1;i <= m; ++i) {
int a,b,c;
read(a);read(b);read(c);
++a,++b;
add(a,b,c);add(b,a,c);
}
dj();
int ans = inf;
for(rint i = 0;i <= K; ++i) {
if(ans > dis[t][i]) ans = dis[t][i];
}
print(ans);
return 0;
}
/*
5 6
0 4
0 1 5
1 2 5
2 3 5
3 4 5
2 3 3
0 2 100
*/
/*
*/
又被卡死的spfa
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((L + R) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
char c = getchar(),f = 1;x = 0;
for(;c ^ '-' && !isdigit(c);c = getchar());
if(c == '-') c = getchar(),f = -1;
for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
x *= f;
}
template<typename xxx>void print(xxx x)
{
if(x<0){putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
const int maxn = 1000110;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
struct edge{
int to,last,val;
}e[maxn<<1];
int tot,head[maxn];
inline void add(int from,int to,int val) {
++tot;
e[tot].to = to;
e[tot].val = val;
e[tot].last = head[from];
head[from] = tot;
}
int dis[maxn][12];
int vis[maxn][12];
int n,m,K;
int s,t;
queue< pair<int,int> >q;
inline void spfa() {
for(rint i = 0;i <= n; ++i) {
for(rint j = 0;j <= K; ++j) {
dis[i][j] = inf;
vis[i][j] = 0;
}
}
q.push(make_pair(s,0));dis[s][0] = 0;
while(q.size()) {
int x = q.front().first;
int y = q.front().second;
q.pop();vis[x][y] = 0;
for(rint i = head[x]; i; i = e[i].last) {
if(dis[e[i].to][y] > dis[x][y] + e[i].val) {
dis[e[i].to][y] = dis[x][y] + e[i].val;
if(!vis[e[i].to][y]) {
vis[e[i].to][y] = 1;
q.push(make_pair(e[i].to,y));
}
}
if(y < K) {
if(dis[e[i].to][y + 1] > dis[x][y]) {
dis[e[i].to][y + 1] = dis[x][y];
if(!vis[e[i].to][y + 1]) {
vis[e[i].to][y + 1] = 1;
q.push(make_pair(e[i].to,y + 1));
}
}
}
}
}
return ;
}
int main()
{
read(n);read(m);read(K);
read(s);read(t);++s,++t;
for(rint i = 1;i <= m; ++i) {
int a,b,c;
read(a);read(b);read(c);
++a,++b;
add(a,b,c);add(b,a,c);
}
spfa();
int ans = inf;
for(rint i = 0;i <= K; ++i) {
if(ans > dis[t][i]) ans = dis[t][i];
}
print(ans);
return 0;
}
/*
*/