题解 [UOJ #592] 新年的聚会
- 一个有 \(m\) 条边的无向图图可以划分成 \(O(\sqrt m)\) 个独立集
事实上,一张无向图可以被划分成 \(\min\{\deg\}+1\) 个独立集
证明考虑染色,那么每个点周围至多有 \(\deg\) 种不同的颜色 - 要找边的交互题考虑先找独立集?
于是怎么暴力怎么划分独立集
比如说,维护当前的所有独立集,每次暴力加进来一个点
然后考虑怎么找边
枚举独立集对 \(S, T\),令 \(|S|\geqslant |T|\)
那么若两者间有边就把 \(S\) 暴力分成两个递归下去
复杂度好像不太对,但是能过
点击查看代码
#include "meeting.h"
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
int id[N], top;
vector<int> sta[N];
vector<pair<int, int>> ans;
bool meeting(vector<int> set);
void solve(vector<int> s, vector<int> t) {
if (!s.size()||!t.size()) return ;
vector<int> tem=s;
for (auto it:t) tem.pb(it);
if (meeting(tem)) return ;
if (s.size()==1&&t.size()==1) {ans.pb({s[0], t[0]}); return ;}
if (s.size()<t.size()) swap(s, t);
int half=s.size()>>1;
vector<int> fir, sec;
for (int i=0; i<s.size(); ++i)
if (i<half) fir.pb(s[i]);
else sec.pb(s[i]);
solve(fir, t);
solve(sec, t);
}
vector<pair<int, int>> solve(int n) {
random_device seed;
mt19937 rand(seed());
for (int i=0; i<n; ++i) id[i]=i;
shuffle(id, id+n, rand);
for (int i=0; i<n; ++i) {
for (int j=1; j<=top; ++j) {
vector<int> tem=sta[j];
tem.pb(id[i]);
if (meeting(tem)) {sta[j].pb(id[i]); goto jump;}
}
sta[++top].pb(id[i]);
jump: ;
}
// cout<<"sta: "; for (int i=1; i<=top; ++i) {cout<<"{"; for (auto it:sta[i]) cout<<it<<','; cout<<"\b}";} cout<<endl;
for (int i=1; i<=top; ++i)
for (int j=i+1; j<=top; ++j)
solve(sta[i], sta[j]);
return ans;
}