Magical Girl Haze
问题分析
题意:最多可以将
m
m
条有向边中的条边的权值变为
0
0
,问到
n
n
的最短距离。
题解:首先建立层相同的图,其中
k
k
个间隔代表次机会,将对于每一条边
(u,v)
(
u
,
v
)
,我们从当前层往底层建立一条权值为
0
0
的单向边(单向边保证不会返回上一层)。然后跑多一维的就可以了。
代码
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int N = 100010;
bool vis[N][11];
LL dist[N][11];
struct node {
int x, k;
LL v;
node(int a, int b, LL v) : x(a), k(b), v(v) {}
friend bool operator<(const node &a, const node &b) {
return a.v > b.v;
}
};
vector<node> E[N];
int main() {
int T;
//freopen("in.txt","r",stdin);
scanf("%d", &T);
while (T--) {
memset(vis, 0, sizeof vis);
int n, m, k, s, t, x, y, z;
LL ans = 1e15;
scanf("%d%d%d", &n, &m, &k);
s = 0, t = n - 1;
for (int i = 0; i <= n; ++i)
E[i].clear();
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &x, &y, &z);
x--, y--;
E[x].push_back(node(y, 0, z));
}
priority_queue<node> q;
memset(dist, 0x3f, sizeof(dist));
dist[s][0] = 0;
q.push((node) {s, 0, 0});
while (!q.empty()) {
node now = q.top();
q.pop();
if (vis[now.x][now.k])
continue;
vis[now.x][now.k] = 1;
int len = E[now.x].size();
for (int i = 0; i < len; ++i) {
node nxt = E[now.x][i];
if (dist[now.x][now.k] + nxt.v < dist[nxt.x][now.k]) {
dist[nxt.x][now.k] = dist[now.x][now.k] + nxt.v;
q.push((node) {nxt.x, now.k, dist[nxt.x][now.k]});
}
if (dist[now.x][now.k] < dist[nxt.x][now.k + 1] && now.k < k) {
dist[nxt.x][now.k + 1] = dist[now.x][now.k];
q.push((node) {nxt.x, now.k + 1, dist[nxt.x][now.k + 1]});
}
}
}
for (int i = 0; i <= k; i++) ans = min(ans, dist[t][i]);
printf("%lld\n", ans);
}
return 0;
}