2019南昌網路賽 Fire-Fighting Hero - 最短路 DIjkstra
阿新 • • 發佈:2020-08-16
有一個消防隊英雄,k個消防隊成員,進行比賽,消防隊英雄到達n個點的最短路的最大值和消防隊成員到達n個點的最短路的最大值的C倍進行比較
方法1:
跑一次DIjkstra,從消防隊英雄出發,然後跑K次最短路,求出值即可
方法2:
建立輔助點0點,0點到K個消防隊成員有一個有向邊,然後跑2次最短路,求出最大值即可
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #define ll long long using namespace std; const int INF = 2147483647; const int N = 1e3 + 5; const int M = 1e6 + 5; ll dis[N];//存路徑 bool vis[N]; struct edge{ int next, to, w; }e[M]; int head[N], tot; inline void add(int u, int v, int w){//鏈式前向星存圖 e[++tot].to = v; e[tot].w = w; e[tot].next = head[u]; head[u] = tot; } struct node{ ll dis;//dis表示到起始點的距離 int pos;//pos表示該點的下標 bool operator < (const node &x)const{//符號過載,對距離排序,針對於在優先佇列裡 return x.dis < dis; } }; void dijkstra(int s, int n){ for(int i = 0; i <= n; i++) dis[i] = INF, vis[i] = 0; dis[s] = 0; std::priority_queue<node> q;//構造優先佇列 q.push((node){dis[s], s});//把初始位置和距離放進優先佇列 while(!q.empty()){ node tmp = q.top(); q.pop(); int u = tmp.pos; if(vis[u]) continue;//如果這個點走過了 vis[u] = 1;//標記走過 for(int i = head[u]; i; i = e[i].next){ int v = e[i].to; if(!vis[v] && dis[v] > dis[u] + e[i].w){ dis[v] = dis[u] + e[i].w; q.push((node){dis[v], v}); } } } } int super[N]; ll teamdis[N]; void solve(){ int V, E, S, K, C; tot = 0; memset(head, 0, sizeof(head)); memset(teamdis, 0x3f, sizeof(teamdis)); scanf("%d%d%d%d%d", &V, &E, &S, &K, &C); for(int i = 1; i <= K; i++) scanf("%d", &super[i]), add(0, super[i], 0); for(int i = 1; i <= E; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); add(u, v, w); add(v, u, w); } dijkstra(S, V); ll maxhero = 0; for(int i = 1; i <= V; i++) maxhero = max(maxhero, dis[i]); ll maxfire = 0; dijkstra(0, V); for(int i = 1; i <= V; i++) maxfire = max(maxfire, dis[i]); printf("%lld\n", maxhero <= maxfire * C ? maxhero : maxfire); } int main(){ int t; scanf("%d", &t); while(t--) solve(); }