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

传送门

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

思路:

  • \(m\leq 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 << '\n'; }
  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 << '\n';
        for(int i = 1; i <= m; i++) {
            cout << edges[i].u << ' ' << edges[i].v << '\n';   
        }
    } 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) << '\n';
        for(auto it : res) {
            cout << edges[it].u << ' ' << edges[it].v << '\n';   
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/heyuhhh/p/12548626.html