-
Step1 Problem:
原题 一个人要逃出城市,给出一个图,但每个节点上有对应的d[i]个怪兽,怪兽会依次堵住当前最短的一条路,给出k个逃生点,请帮他计算一下最坏情况下他能逃出城市的最短时间。
-
Step2 Ideas:
从k个逃生点反向跑到起点,这样可以保证到当前点的路一定是可以走的路,用n个优先队列维护出第 d[i] + 1 个小的dis值便是当前点的所能走的最短路
-
Step3 code:
/** * Youth gives you light please don't let it down. * ▄▄▄▄▄ * ▀▀▀██████▄▄▄ _______________ * ▄▄▄▄▄ █████████▄ / * ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Gotta go fast! | * ▀▀█████▄▄ ▀██████▄██ | _________________/ * ▀▄▄▄▄▄ ▀▀█▄▀█════█▀ |/ * ▀▀▀▄ ▀▀███ ▀ ▄▄ * ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌ ______________________________ * ██▀▄▄▄██▀▄███▀ ▀▀████ ▄██ █ \ * ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███ ▌▄▄▀▀▀▀█_____________________________// * ▌ ▐▀████▐███▒▒▒▒▒▐██▌ * ▀▄▄▄▄▀ ▀▀████▒▒▒▒▄██▀ * ▀▀█████████▀ * ▄▄██▀██████▀█ * ▄██▀ ▀▀▀ █ * ▄█ ▐▌ * ▄▄▄▄█▌ ▀█▄▄▄▄▀▀▄ * ▌ ▐ ▀▀▄▄▄▀ * ▀▀▄▄▀ ██ * ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ * - ▌ GNU C++17 7.3.0 ▀ ▀ * - ▌ ▀ * /- ▌ Go Go Go ! ▀ ▀ * / ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀ * ██ **/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> #include<cassert> #include<cctype> #include<cmath> #include<cstdlib> #include<ctime> #include<deque> #include<iomanip> #include<list> #include<map> #include<queue> #include<set> #include<stack> #include<vector> #define lt k<<1 #define rt k<<1|1 #define int ll using namespace std; typedef long long ll; typedef long double ld; #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); #define mem(a, b) memset(a, b, sizeof(a)) const double pi = acos(-1.0); const double eps = 1e-6; const ll mod = 1e9 + 7; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; const int maxn = 1e6 + 5; int head[maxn], cnt, dis[maxn]; bool vis[maxn]; int e[maxn], d[maxn]; int n, m, k; struct node { int v, w; node () {} node(int a, int b) {v = a, w = b;} bool operator < (const node & b) const { return w > b.w;} }; struct Edge { int v, w, next; Edge () {} Edge(int a, int b, int c) {v = a, w = b, next = c;} } edge[maxn * 2]; void add_edge(int u, int v, int w) { edge[cnt] = (Edge) {v, w, head[u]}; head[u] = cnt++; edge[cnt] = (Edge) {u, w, head[v]}; head[v] = cnt++; } priority_queue<int> di[maxn]; void dij() { priority_queue<node> q; for(int i = 0; i < k; i++) { dis[e[i]] = 0; q.push((node){e[i], dis[e[i]]}); } while(!q.empty()) { node now = q.top(); q.pop(); int u = now.v; if(vis[u]) continue; vis[u] = true; for(int i = head[u]; ~i; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; di[v].push(dis[u] + w); if(di[v].size() > d[v] + 1) di[v].pop(); if(di[v].top() < dis[v] && di[v].size() > d[v]) { dis[v] = di[v].top(); q.push((node){v, dis[v]}); } } } } signed main() { ios; int T; cin >> T; while(T--) { cnt = 0; cin >> n >> m >> k; for(int i = 1;i <= n; i++) { dis[i] = inf; vis[i] = false; head[i] = -1; while(!di[i].empty()) di[i].pop(); } for(int i = 0; i < k; i++) cin >> e[i]; for(int i = 1; i <= n; i++) cin >> d[i]; while(m--) { int u, v, w; cin >> u >> v >> w; add_edge(u, v, w); } dij(); if(dis[1] == inf) cout << -1 << endl; else cout << dis[1] << endl; } return 0; }