【】maze
【链接】点击打开链接
【题意】
小 T 被放到了一个迷宫之中,这个迷宫由 n 个节点构成,两个节点之间可能存在多条无 向边,小 T 的起点为 1 号节点,终点为 n 号节点。有 m 条无向边,对于每一条无向边,存在 一个喋血值(∈N*,且≤100),即走过这条边的花费。另外,还有 k 个节点上有治疗药,即 若小 T 走到这个节点上时(不妨称这个点为治愈点),他身上所累积的喋血值会归零。小 T 希望以最小的喋血值走完迷宫。
1<=n<=5000,1<=k<=n,1<=m<=25000.
【题解】
考虑走到了治愈点.
则肯定喋血值变成0了。
之前走多少的喋血值都无所谓了。
于是,考虑这个人走的最后一个治愈点是哪个?
枚举即可。
然后求出治愈点到n的最短路。
或者,没有经过治愈点,则输出一条从1到n的最短路。
【错的次数】
0
【反思】
在这了写反思
【代码】
#include <bits/stdc++.h>
using namespace std;
const int N = 5e3, INF = 0x3f3f3f3f;
int n, m, k, dis[N+10],f[N+10];
vector <pair<int,int> > G[N + 10];
queue <int> dl;
bool inq[N + 10];
int ff(int x) {
if (f[x] == x) return x;
else
return f[x] = ff(f[x]);
}
int main() {
//freopen("F:\\rush.txt", "r", stdin);
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m >> k;
for (int i = 1; i <= n; i++) f[i] = i;
for (int i = 1; i <= m; i++) {
int x, y, z;
cin >> x >> y >> z;
if (ff(x) != ff(y)) f[ff(x)] = ff(y);
G[x].push_back(make_pair(y, z)), G[y].push_back(make_pair(x, z));
}
if (ff(1) != ff(n)) return cout << "Oh no!" << endl, 0;
memset(dis, INF, sizeof dis);
dis[n] = 0, inq[n] = 1;
dl.push(n);
while (!dl.empty()) {
int x = dl.front(); dl.pop();
inq[x] = false;
for (auto temp : G[x]) {
if (dis[temp.first] > dis[x] + temp.second) {
dis[temp.first] = dis[x] + temp.second;
if (!inq[temp.first]) {
inq[temp.first] = true;
dl.push(temp.first);
}
}
}
}
int ans = dis[1];
for (int i = 1; i <= k; i++) {
int x;
cin >> x;
if (ff(x) == ff(1) && ff(x) == ff(n)) ans = min(ans, dis[x]);
}
cout << ans << endl;
return 0;
}
浙公网安备 33010602011771号