题目链接 : 最大化最短路
题目描述 :
题目思路 :
如果我们选出了两个候选点 a1,a2,则 : 1 -> n 的最短路的长度只有三种情况 :
- 保持原来的最短路,即最短路不被加入边所影响
- 最短路变为 1 -> a1 -> a2 -> n
- 最短路变为 1 -> a2 -> a1 -> n
即 :加入两点后,最短路位上述的三种情况中的最小值
然后题目等价于 找到点对 a1,a2 使得上述得到的 最短路 最大 即可
所以记 :
d1[i] -> 1 到 i 的最短路长度
d2[i] -> n 到 i 的最短路长度
那么针对上述的三种情况就是分别对应 :
- d1[n]
- d1[a1] + d2[a2] + 1
- d1[a2] + d2[a1] + 1
如果我们枚举每一种点对情况,则 : 时间复杂度到 O(N^2) 会超时
所以我们考虑什么情况下 第二种情况 恒小于 第三种情况 :
d1[a1] + d2[a2] + 1 < d1[a2] + d2[a1] + 1
-> d1[a1] - d2[a1] < d1[a2] - d2[a2]
所以我们把特殊点按照 d1[i] - d2[i] 来排序
这样当我们遍历到点 j ,往前选取点 i ,那么 2 , 3 中的最短距离就是 情况 2
那么又因为 d2[j] + 1 是 定值 , 所以只需要遍历的过程中保存 d1[i] 的最大值即可
题目代码 :
#include <iostream>
#include <bits/stdc++.h>
#include <ctime>
#include <algorithm>
#include <stdlib.h>
#define x first
#define y second
using namespace::std;
using LL = long long;
using ULL = unsigned long long;
// ULL 是可以自己取模的
using PII = pair<int,int>;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int dir[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
int n,m,k;
const int N = 2e5 + 7;
vector<vector<int>> g;
int a,b;
int w[N];
int d1[N];// d1[i] : 1 -> i 的最短距离
int d2[N];// d2[i] : n -> i 的最短距离
// 计算 d1 d2
void SPFA() {
bool h1[n + 1] = {false};
bool h2[n + 1] = {false};
h1[1] = true;
h2[n] = true;
queue<int> q;
q.push(1);
while(!q.empty()) {
int len = q.size();
while(len --) {
int t = q.front(); q.pop();
for(auto& next : g[t]) {
if(!h1[next]) {
h1[next] = true;
d1[next] = d1[t] + 1;
q.push(next);
}
}
}
}
q.push(n);
while(!q.empty()) {
int len = q.size();
while(len --) {
int t = q.front(); q.pop();
for(auto& next : g[t]) {
if(!h2[next]) {
h2[next] = true;
d2[next] = d2[t] + 1;
q.push(next);
}
}
}
}
return ;
}
int main() {
cin >> n >> m >> k;
int x;
g.resize(n + 1);
for(int i = 0;i < k;i ++) {
scanf("%d", &w[i]);
}
for(int i = 0;i < m;i ++) {
scanf("%d%d", &a, &b);
g[a].push_back(b);
g[b].push_back(a);
}
d1[1] = 0;
d2[n] = 0;
SPFA();
sort(w,w + k,[&](int& a,int& b) {
return d1[a] - d2[a] < d1[b] - d2[b];
});// 按照差值的升序排序
// 遍历到某一个数字的情况 : 往前找最大数
int res = 0;
int ma = d1[w[0]];
for(int i = 1;i < k;i ++) {
res = max(res,d2[w[i]] + 1 + ma);
ma = max(ma,d1[w[i]]);
}
cout<<min(res,d1[n])<<endl;
return 0;
}