思路:
将一条无向边 (i, j) 拆分成两个有向边,每个有向边转换为一个点,给一个编号,用 dist[ei]
表示从 1号点到边 ei 的最短路径长度,这样方便我们转移。
接着由于边权为1,直接bfs,每次扩展的时候都判断一下要扩展的点可不可以从 ei 转移过去,这个可以预处理出来,最后记录前驱,递归输出。
至于无解判断,当所有到达n的点距离都为INF时即无解。
可是这个代码在 Test7 WA了,原因是无解判断错了,本来是有解的,大佬们求求调一调8 qwq!
// Problem: Shortest Path
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF59E
// Memory Limit: 250 MB
// Time Limit: 3000 ms
// Author: Moyou
// Copyright (c) 2022 Moyou All rights reserved.
// Date: 2022-11-27 15:39:41
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#define x first
#define y second
#define INF 0x7f7f7f7f
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 3000 + 10, M = 20010, K = 1e5 + 10;
int h[N], ne[M], e[M], idx;
int dist[M];
void add(int a, int b)
{
e[++idx] = b, ne[idx] = h[a], h[a] = idx;
}
struct trip
{
int a, b, c;
bool operator<(const trip &T) const
{
if (a != T.a)
return a < T.a;
else
return b < T.b;
}
} dis[K];
vector<int> forbid[M]; // 记录对于每一个边不可行的点
map<PII, int> es; // 点对对应的边编号
map<int, PII> ep; // 边编号对应的点对
bool mark[N]; // 每次扩展的时候计算,mark[i]表示当前边是否能扩展到i点
bool st[M]; // bfs
int n, m, k;
int pred[M]; // 前驱
int bfs(int s)
{
memset(dist, 0x7f, sizeof dist);
queue<PII> q;
for (int i = h[s]; ~i; i = ne[i])
{
int j = e[i];
q.push({s, j});
dist[es[{s, j}]] = 1;
}
while (q.size())
{
auto t = q.front();
q.pop();
int edge = es[{t.x, t.y}];
if(t.y == n && dist[es[{t.x, t.y}]] != INF) return t.x;
if(st[edge]) continue;
st[edge] = 1;
for (int i = 1; i <= n; i++)
mark[i] = 1;
for (auto i : forbid[edge])
mark[i] = 0;
for (int i = h[t.y]; ~i; i = ne[i])
{
int j = e[i], e2 = es[{t.y, j}];
if (!mark[j])
continue;
dist[e2] = dist[edge] + 1;
if(!pred[e2])pred[e2] = edge;
q.push({t.y, j});
}
}
return -1;
}
int cnt;
vector<int> out;
void write(int p)
{
if(ep[p].x == 1)
{
cnt ++;
out.push_back(ep[p].y);
// cout << ep[p].y << ' ';
return ;
}
// cout << p << ' ' << ep[p].x << ' ' << ep[p].y << endl;
cnt ++;
write(pred[p]);
out.push_back(ep[p].y);
// cout << ep[p].y << ' ';
}
int main()
{
memset(h, -1, sizeof h);
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
es[{a, b}] = 2 * (i - 1) + 1;
es[{b, a}] = 2 * (i - 1) + 2;
ep[2 * (i - 1) + 1] = {a, b};
ep[2 * (i - 1) + 2] = {b, a}; // 设置编号
}
for (int i = 1; i <= k; i++)
cin >> dis[i].a >> dis[i].b >> dis[i].c;
sort(dis + 1, dis + k + 1);
for (int i = 1; i <= k; i++)
{
forbid[es[{dis[i].a, dis[i].b}]].push_back(dis[i].c);
}
int ans = bfs(1);
if (ans == -1)
{
puts("-1");
return 0;
}
out.push_back(1);
write(es[{ans, n}]);
cout << cnt << endl;
for(auto i : out) cout << i << ' ';
return 0;
}
欧内该!qwq