题意

主角PMP要搭车离开公园,有一个有n个节点m条边的无向图,PMP要从s走到t

因为主角PMP的记性不好,因此他需要志愿者的帮助,帮他找到路,PMP最多只能记住p距离的路线,志愿者总是会选择最好的路径,如果在p走不到时,会给他指向下一个在这条路径上的志愿者的位置,让我们求p的最小值

说实话这个地方我也看了很久,复述的也不太明白

直接说就是,有k个特殊的点,我记录从s到t的最短路径w,如果中间遇到了特殊节点,路径长度就清空w,那么这个w就是p的最小值

主要是题目没看懂,看懂了题目就很明白了,就是从起点出发,然后找最短路径,记录路径的长度,如果遇到了有志愿者的点,路径长度就清空为0 ,

用优先队列来实现,将与当前节点相连的路线放进优先队列,按照路线终点来排序(按照起点排序也行,起点排序跑的还更快),找到终点break即可,

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
const ll MOD = 1e9 + 7;
#define pai pair<int, int>
const int N = 1e5 + 7;
const int INF = 0x3f3f3f3f;

struct node{
    int u , w;
    bool operator <(const node &a) const{
        return u < a.u;
    }
};

ll n , m , k;
vector<int>edge[N];
bool vis[N];
int s , t;
int dis[N];



int main(void){
    cin>>n>>m>>k;
    int x , u , v ,w;
    for(int i = 1 ; i <= k ; ++i){
        cin>>x;
        vis[x] = 1;
    }
    for(int i = 1 ; i <= m ; ++i){
        cin>>u>>v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    cin>>s>>t;
    int ans = 0;
    memset(dis , 0x3f , sizeof(dis));
    priority_queue<pai , vector<pai> , greater<pai>> pq;
    pq.push({0 , s});
    while(pq.size()){
        w = pq.top().first , u = pq.top().second;
        pq.pop();
        ans = max(ans , w);
        if(u == t)  break;
        if(vis[u])  w = 0;
        for(auto& v : edge[u]){
            if(dis[v] > w + 1){
                dis[v] = w + 1;
                pq.push({dis[v] , v});
            }
        }
    }
    if(dis[t] == INF)   ans = -1;
    printf("%d\n" , ans);
    return 0;
}