• 【cf1307D】D. Cow and Fields(bfs序贪心)


    传送门

    题意:
    给出一个(n)个点(m)条边的无向图,然后给出(k)个关键点。
    现在要在一对关键点中添加一条边,问最后从(1)(n)的最短路的最大值为多少。

    思路:

    • (1)号点出发得到每个点的(bfs)序,然后将图按照(bfs)序分层。再从(n)号点跑一遍得到对应的(bfs)序。
    • 显然一个点在一条从(1)(n)的路径上,当且仅当(bfs1_i ot ={inf},bfs2_i ot ={inf})
    • 若存在一个关键点不在从(1)(n)的最短路中,那么答案就为(1 o 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 << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    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] << '
    ';
                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 << '
    ';
    }
     
    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;
    }
    
  • 相关阅读:
    Codeforces Round #307 (Div. 2)E. GukiZ and GukiZiana
    bzoj2957: 楼房重建,分块
    分块入门。
    poj3690 Constellations
    Codeforces Round #451 (Div. 2)F. Restoring the Expression 字符串hash
    Codeforces Round #456 (Div. 2)D. Fishes
    Codeforces Round #450 (Div. 2)D. Unusual Sequences
    快速排序+分治法
    哈夫曼编码课程设计+最小优先对列建树。
    浅谈差分约束系统
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12326726.html
Copyright © 2020-2023  润新知