题解 [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;
}
posted @ 2022-06-11 17:38  Administrator-09  阅读(2)  评论(0编辑  收藏  举报