【 最短路 && 思维 】Escape Plan

  • 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;
}

 

posted @ 2019-07-29 09:28  Mr.XuAMis.Liu  阅读(194)  评论(0编辑  收藏  举报