【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;
}
posted @ 2020-02-18 16:23  heyuhhh  阅读(334)  评论(0编辑  收藏  举报