题目链接
题解:假设我们连接了两个点a,b,那么这条路是从1到a的距离+a到b的距离+b到n的距离。那么我们首先就要预处理出来两个距离,分别是1到各个点的最短距离为d1,另一个就是n到各个点的最短距离d2。我们再有了这个之后,就可以得到距离为min(d1[a]+1+d2[b],d1[b]+1+d2[a]),但是我们有了它以后如果暴力遍历所有点的话,是O(n²),很明显是会超时的。
我们可以把这两个式子中的元素交换交换下,会得到这样的一个式子,d1[a]-d1[b],d2[a]-d2[b],而我们要找的是两个当中比较小的,所以我们按照这个来进行排序。然后再遍历即可得到答案。
#include<bits/stdc++.h>
#define ll long long
#define pr pair<int,int>
#define ios ios::sync_with_stdio(false)
#define CRL(a) memset(a,0,sizeof a)
#define endl "\n"
using namespace std;
const int N = 2e5 + 5;
int d1[N], d2[N], a[N];
bool f[N];
struct node
{
int to, next, w;
} e[N * 2];
int head[N], cnt = 0;
void add(int u,int v,int w)
{
e[++cnt] = {v, head[u], w};
head[u] = cnt;
}
void bfs(int a,int d[])
{
memset(d, 0x3f, N*4);
memset(f, 0, sizeof f);
queue<int> q;
q.push(a);
d[a] = 0;
f[a] = 1;
while(q.size())
{
int b = q.front();
q.pop();
f[b] = 0;
for (int i = head[b]; i;i=e[i].next)
{
int v = e[i].to, w = e[i].w;
if(d[v]>d[b]+w)
{
d[v] = d[b] + w;
if(f[v]==0)
q.push(v), f[v] = 1;
}
}
}
}
bool cmp(int a,int b)
{
return d1[a] - d2[a] < d1[b] - d2[b];
}
int main()
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= k;i++)
{
cin >> a[i];
}
for (int i = 1; i <= m;i++)
{
int u, v, w;
cin >> u >> v ;
add(u, v, 1);
add(v, u, 1);
}
bfs(1, d1);
bfs(n, d2);
sort(a + 1, a + 1 + k, cmp);
int ans = 0, x = d1[a[1]];
for (int i = 2; i <= k;i++)
{
int b = a[i];
ans = max(ans, d2[b] + x + 1);
x = max(x, d1[b]);
}
cout << min(d1[n],ans);
}