题目链接:Codeforces - Cow and Fields
我们先正反两次bfs,求出点1到所有点的最短路和点n到所有点的最短路。
然后对于k个关键点,我们要使得 min(d1[i]+1+d2[j] , d1[j]+1+d2[i]) 最大。
所以问题就转变为求这个的最大值。
我们按照 d1[i] - d2[i] 从大到小排序。
然后从前往后枚举,当我们枚举到 i 时,保证了前面的是更大的那一对,所以我们就用最小值更新即可。
然后维护一个最大的d2,保证转移一定是合法的。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10,M=N<<1;
int n,m,k,a[N],p[N],flag,d[N],d1[N],vis[N],res;
int head[N],nex[M],to[M],tot;
inline void ade(int a,int b){to[++tot]=b; nex[tot]=head[a]; head[a]=tot;}
inline void add(int a,int b){ade(a,b); ade(b,a);}
int cmp(int a,int b){return d[a]-d1[a]>d[b]-d1[b];}
void bfs(int s,int *d){
queue<int> q; d[s]=0; q.push(s);
while(q.size()){
int u=q.front(); q.pop();
for(int i=head[u];i;i=nex[i]) if(d[to[i]]==-1){
d[to[i]]=d[u]+1; q.push(to[i]);
}
}
}
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=k;i++) scanf("%d",&a[i]);
for(int i=1,x,y;i<=m;i++) scanf("%d %d",&x,&y),add(x,y);
memset(d,-1,sizeof d),memset(d1,-1,sizeof d1);
bfs(1,d); bfs(n,d1);
sort(a+1,a+1+k,cmp); int mx=-1e9;
for(int i=1;i<=k;i++) res=max(res,d[a[i]]+1+mx),mx=max(mx,d1[a[i]]);
cout<<min(d[n],res);
return 0;
}