1. 程式人生 > 實用技巧 >2019南昌網路賽 Fire-Fighting Hero - 最短路 DIjkstra

2019南昌網路賽 Fire-Fighting Hero - 最短路 DIjkstra

有一個消防隊英雄,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();
}