• 【cf1186F】F. Vus the Cossack and a Graph(dfs树+随机化)


    传送门

    题意:
    给定一个(n)个点(m)条边的无向图,定义(d_i)为第(i)个点的度数。
    现在要去掉一些边,使得最后保留(displaystylelceilfrac{n+m}{2} ceil)条边。
    定义(f_i)为最终图中点的度数,那么满足对于(1leq ileq n),都有(displaystylelceilfrac{d_i}{2} ceilleq f_i)
    输出最后保留的边。

    思路:

    • (mleq n),显然直接保留所有的边即可;
    • (m>n),发现我们只需要去掉所有的环即可满足条件。注意到一个环中我们肯定可以去掉一条边使得度数满足条件,那么也就是可以去掉所有的环。
    • 那么通过(dfs)构建(dfs)树直接去环即可。
    • 只进行一次(dfs)的话可能会因为度数限制不能去掉所有的环,那么我们只需要随机选取若干次起点去环即可。

    至于正确性的证明不是很会,但感觉应该可以在满足度数限制的条件下去掉所有的环。
    如果有大佬知道的话希望能够不吝赐教。
    代码如下:

    /*
     * Author:  heyuhhh
     * Created Time:  2020/3/19 20:57:08
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <random>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #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...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5;
    
    int n, m;
    
    struct Edge {
        int u, v;
    } edges[N];
    
    vector <pii> G[N];
    vector <int> res;
    bool chk[N], out[N];
    int d[N], f[N];
    
    void dfs(int u, int fa) {
        chk[u] = true;
        for(auto it : G[u]) if(it.fi != fa) {
            int v = it.fi, i = it.se;
            if(out[i]) continue;
            if(chk[v]) {
                if(f[u] - 1 >= (d[u] + 1) / 2 && f[v] - 1 >= (d[v] + 1) / 2) {
                    out[i] = true;
                    --f[u], --f[v];
                }
                continue;
            }
            dfs(v, u);
        }   
    }
    
    mt19937 rnd(time(NULL));
    
    void run() {
        cin >> n >> m;
        for(int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            G[u].push_back(MP(v, i));
            G[v].push_back(MP(u, i));
            edges[i] = Edge {u, v};
            ++d[u], ++d[v];
        }
        for(int i = 1; i <= n; i++) f[i] = d[i];
        if(m <= n) {
            cout << m << '
    ';
            for(int i = 1; i <= m; i++) {
                cout << edges[i].u << ' ' << edges[i].v << '
    ';   
            }
        } else {
            for(int i = 1; i <= 20; i++) {
                memset(chk, false, sizeof(chk));
                int rt = rnd() % n + 1;
                dfs(rt, 0);   
            }
            for(int i = 1; i <= m; i++) if(!out[i]) res.push_back(i);
            cout << sz(res) << '
    ';
            for(auto it : res) {
                cout << edges[it].u << ' ' << edges[it].v << '
    ';   
            }
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    【linux基础err】bash: cannot create temp file for here-document: No space left on device
    【python基础】argparse模块
    第23课 优先选用make系列函数
    第22课 weak_ptr弱引用智能指针
    第21课 shared_ptr共享型智能指针
    第20课 unique_ptr独占型智能指针
    第19课 lambda vs std::bind
    第18课 捕获机制及陷阱
    第17课 lambda表达式
    第16课 处理万能引用和重载的关系
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12548626.html
Copyright © 2020-2023  润新知