【cf1307D】D. Cow and Fields(bfs序贪心)
题意:
给出一个\(n\)个点\(m\)条边的无向图,然后给出\(k\)个关键点。
现在要在一对关键点中添加一条边,问最后从\(1\)到\(n\)的最短路的最大值为多少。
思路:
- 从\(1\)号点出发得到每个点的\(bfs\)序,然后将图按照\(bfs\)序分层。再从\(n\)号点跑一遍得到对应的\(bfs\)序。
- 显然一个点在一条从\(1\)到\(n\)的路径上,当且仅当\(bfs1_i\not ={inf},bfs2_i\not ={inf}\)。
- 若存在一个关键点不在从\(1\)到\(n\)的最短路中,那么答案就为\(1\to n\)的最短路;否则,答案不会变大,此时我们按照\(bfs1\)或\(bfs2\)排序,贪心按照\(bfs\)序从小到大连边连边更新答案即可。
- 贪心的正确性:因为要使得最后答案尽可能大,若现在\(bfs1_i<bfs1_j<bfs1_k\),如果我们连接\((i,k)\),显然路径长度会变得更小,不如连接\((i,j),(j,k)\)优。
代码如下:
/*
* Author: heyuhhh
* Created Time: 2020/2/18 9:39:26
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e5 + 5;
int n, m, k;
int a[N];
vector <int> G[N];
int d1[N], d2[N];
bool chk[N], vis[N];
void bfs(int s, int* d) {
fill(d + 1, d + n + 1, INF);
queue <int> q; q.push(s);
d[s] = 0;
while(!q.empty()) {
int u = q.front(); q.pop();
for(auto v : G[u]) {
if(d[v] > d[u] + 1) {
d[v] = d[u] + 1;
q.push(v);
}
}
}
}
void run(){
for(int i = 1; i <= k; i++) cin >> a[i];
for(int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
bfs(1, d1); bfs(n, d2);
for(int i = 1; i <= n; i++) {
if(d1[i] != INF && d2[i] != INF) chk[i] = true;
}
multiset <pii> s;
for(int i = 1; i <= k; i++) {
if(!chk[a[i]]) {
cout << d1[n] << '\n';
return;
}
s.insert(MP(d1[a[i]], a[i]));
}
int ans = 0;
for(auto it = s.begin(); it != s.end(); ++it) {
if(it == s.begin()) continue;
auto it2 = it; --it2;
ans = max(ans, min(min(d1[n], d1[it2 -> se] + d2[it -> se] + 1), d1[it -> se] + d2[it2 -> se] + 1));
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> m >> k) run();
return 0;
}
重要的是自信,一旦有了自信,人就会赢得一切。