【链接】点击打开链接
【题意】
小 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; }