其他分享
首页 > 其他分享> > [WC2022] 杂题选讲-钱易

[WC2022] 杂题选讲-钱易

作者:互联网

新年的聚会

题目描述

点此看题

解法

其实用分治的思想很容易解决聚会个数的限制,我们可以枚举一个点对其他点做分治,那么询问次数是 \(O(m\log n)\),但是这样做总人数不满足条件。

关键结论:对于一个边数为 \(m\) 的图可以划分出 \(\sqrt m\) 个独立集。对于度数 \(\geq\sqrt m\) 的点可以单独划分成独立集,对于度数 \(<\sqrt m\) 的点,考虑邻接点颜色的 \(\tt mex\) 必然小于 \(\sqrt m\),所以可以根据 \(\tt mex\) 确定它的颜色(颜色就是指独立集标号)

划分独立集可以对于每一个点枚举它划分在哪个独立集中,然后用 \(\tt meeting\) 函数检验。然后我们对于枚举两个独立集,用分治的方法来确定他们的边,也就是把较大的那个集合拆成两半,然后递归下去即可,出口就是两个集合大小都为 \(1\)

复杂度显然是说不清楚的,但是上面是一个平衡复杂度的做法,如果不够放心可以在划分独立集的时候把所有点 \(\tt random\_shuffle\) 一遍。

总结

图论问题常用度数 \(\sqrt m\) 分类的方法来平衡复杂度

#include <cstdio>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include "meeting.h"
using namespace std;
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int M = 1005;
int cnt=0,p[M];
vector<pii> ans;vector<int> s[M];
void cdq(int x,int y,int xl,int xr,int yl,int yr)
{
	if(xr-xl<yr-yl) swap(x,y),swap(xl,yl),swap(xr,yr);
	if(xl==xr && yl==yr)
	{
		ans.pb(mp(s[x][xl],s[y][yl]));
		return ;
	}
	int mid=(xl+xr)>>1;vector<int> A,B;
	for(int i=yl;i<=yr;i++)
		A.pb(s[y][i]),B.pb(s[y][i]);
	for(int i=xl;i<=xr;i++)
		i<=mid?A.pb(s[x][i]):B.pb(s[x][i]);
	if(!meeting(A)) cdq(x,y,xl,mid,yl,yr);
	if(!meeting(B)) cdq(x,y,mid+1,xr,yl,yr);
}
vector<pii> solve(int n)
{
	srand(time(0));
	for(int i=0;i<n;i++) p[i]=i;
	random_shuffle(p,p+n);
	for(int w=0;w<n;w++)
	{
		int fl=0,i=p[w];
		for(int j=1;j<=cnt;j++)
		{
			s[j].pb(i);
			if(meeting(s[j])) {fl=1;break;}
			s[j].pop_back();
		}
		if(!fl) s[++cnt].pb(i);
	}
	for(int i=1;i<=cnt;i++)
		for(int j=i+1;j<=cnt;j++)
		{
			int l1=s[i].size(),l2=s[j].size();
			cdq(i,j,0,l1-1,0,l2-1);
		}
	return ans;
}

标签:int,复杂度,选讲,sqrt,WC2022,vector,include,杂题,define
来源: https://www.cnblogs.com/C202044zxy/p/15856601.html