Description
分层图最短路,就是在分层图上解决最短路问题。
主要是应用于变化的最短路问题,问题常表现为一个最短路问题上加一些手脚,如减小一些边权,改变一些连接,但事先又不知道,或可以自由选择改变哪个边,最终求最短路等等。由于无法知道改变了那些边,所以用到分层图思想。
1.一种解决方法是多开一维记录状态,多开的维度记录状态的种类数即为分层数
2.另一种解决方法是可以理解为平行宇宙 一样的东西 就是把原图复制出来
k
k
k个,然后在原图连接的基础上,在相邻层中间加一些要求的变化边,通常是单向的(保证从每一层到下一层不再回来),再跑最短路。
个人觉得第一种更好一点。第二种方法需多建很多点和边,容易
M
L
E
MLE
MLE。
本题就是取自于
B
Z
O
J
2763
BZOJ2763
BZOJ2763,不过是有向边且数据范围扩大了。
题意就是从
1
→
n
1 \to n
1→n的最短路径长度,其中最多可以使得
K
K
K条路径免费。
Input
1
≤
T
≤
5
1 \leq T\leq 5
1≤T≤5
N
≤
1
0
5
N\leq 10^5
N≤105
M
≤
2
∗
1
0
5
M\leq 2*10^5
M≤2∗105
K
≤
10
K\leq 10
K≤10
0
≤
c
i
≤
1
0
9
0 \leq c_i\leq 10^9
0≤ci≤109
Output
最短路径长度
Solution
1.一种解决方法是多开一维记录状态,多开的维度记录状态的种类数即为分层数.
d
i
s
t
[
i
]
[
j
]
:
表
示
到
达
i
点
的
第
j
层
最
短
路
径
。
也
可
以
说
到
达
i
点
使
用
了
j
次
免
费
路
径
的
最
短
路
径
。
dist[i][j]:表示到达i点的第j层最短路径。也可以说到达i点使用了j次免费路径的最短路径。
dist[i][j]:表示到达i点的第j层最短路径。也可以说到达i点使用了j次免费路径的最短路径。
答
案
就
是
d
i
s
t
[
n
]
[
k
]
答案就是dist[n][k]
答案就是dist[n][k]
更
新
的
时
候
除
了
对
当
前
层
的
点
松
弛
还
要
对
下
一
层
的
点
进
行
松
弛
。
更新的时候除了对当前层的点松弛还要对下一层的点进行松弛。
更新的时候除了对当前层的点松弛还要对下一层的点进行松弛。
Codes
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
struct Edge {
int to;
ll cost;
Edge(){}
Edge(int _t,ll _c) {to = _t;cost = _c;}
};
vector<Edge> ways[maxn];
struct qNode {
int x,y;
ll cost;
qNode(){}
qNode(int _t,int _k,ll _c) {x = _t;y = _k;cost = _c;}
bool operator < (const qNode &a) const {
return cost > a.cost;
}
};
int n,m,k,from,to;
bool vis[maxn][15];
ll dist[maxn][15];
inline void init() {
for(int i=0;i<maxn;i++) ways[i].clear();
}
inline void addedge(int u,int v,ll c) {
ways[u].push_back(Edge(v,c));
}
ll solve(int from,int to) {
memset(vis,0,sizeof(vis));
memset(dist,0x3f,sizeof(dist));
//printf("%lld\n",dist[0][0]);
priority_queue<qNode> qu;
while(!qu.empty()) qu.pop();
dist[from][0] = 0;
qu.push(qNode(from,0,dist[from][0]));
qNode now;
Edge tmp;
while(!qu.empty()) {
now = qu.top(); qu.pop();
int u = now.x,step = now.y;
vis[u][step] = true;
for(int i=0;i<ways[u].size();i++) {
tmp = ways[u][i];
int v = tmp.to;ll cost = tmp.cost;
if(!vis[v][step] && dist[v][step] > dist[u][step] + cost) {
dist[v][step] = dist[u][step] + cost;
qu.push(qNode(v,step,dist[v][step]));
}
/// 对下一层进行松弛
if(step == k) continue;
if(!vis[v][step+1] && dist[v][step+1] > dist[u][step]) {
dist[v][step+1] = dist[u][step];
qu.push(qNode(v,step+1,dist[v][step+1]));
}
}
}
return dist[to][k];
}
int main()
{
int caset;scanf("%d",&caset);
while(caset--) {
scanf("%d%d%d",&n,&m,&k);
init();
// scanf("%d%d",&from,&to);
ll c;
for(int i=0,u,v;i<m;i++) {
scanf("%d%d%lld",&u,&v,&c);
addedge(u,v,c);
}
ll ans = solve(1,n);
printf("%lld\n",ans);
}
return 0;
}