首页 > 其他分享 >洛谷 P5811 - [IOI2019] 景点划分

洛谷 P5811 - [IOI2019] 景点划分

时间:2023-10-02 16:33:22浏览次数:47  
标签:IOI2019 子树 洛谷 P5811 siz int MAXN swap ord

小清新构造题。

不妨假设 \(a\le b\le c\)。显然我们会让大小为 \(a,b\) 的部分连通,这样肯定是不劣的。建出 DFS 树,考虑其重心 \(r\),如果 \(r\) 的某个子树大小 \(\ge a\),我们在这个子树内挑一个大小为 \(a\) 的连通块,在抠掉这个子树之外的部分挑一个大小为 \(b\) 的连通块即可。因为 \(r\) 是重心,所以外面的部分大小 \(\ge\dfrac{n}{2}\),而显然 \(b\le\dfrac{n}{2}\),所以一定是可以挑出来的。

否则,所有子树大小都 \(\le\dfrac{a}{2}\),如果图仅仅只是一棵树的话,那想要凑出 \(a\) 和 \(b\) 的话都需要经过重心,此时是不可行的。但是如果是一张普通图的话,则可能可以通过非树边使得某些子树在不经过重心的情况下连通。此时我们采取这样的策略:依次考虑每个子树,DFS 一遍去掉重心的情况下,它能到达的部分,如果该连通块大小 \(\ge a\),就说明方案存在,否则方案不存在。具体构造是,不断扩展与当前子树相连相连的子树,直到连通块大小 \(\ge a\),这样我们就构造出了大小 \(=a\) 的连通块,而我们可以证明剩余部分大小 \(\ge b\),这是因为每个子树大小 \(<a\),因此我们此时选择的部分大小 \(<2a\),这样剩余部分大小 \(>n-2a=b+c-a>b\)。

具体实现时候,如果我们采用以 \(1\) 为根 DFS 的方式求 DFS 方式,那么假设以 \(1\) 为根时 \(r\) 的父亲为 \(fa\),那么可以证明,在每个子树大小都 \(<a\) 的情况下,我们只用考虑与 \(fa\) 所在的子树相连的子树集合即可,这是因为 DFS 树不存在横叉边,因此所有有用的非树边都经过 \(fa\) 所在的子树。

const int MAXN=1e5;
const int MAXM=2e5;
const int INF=0x3f3f3f3f;
int n,m,A,B,C,ord[4],vis[MAXN+5],fa[MAXN+5],siz[MAXN+5],mx[MAXN+5],cent,res[MAXN+5];
struct graph{
	int hd[MAXN+5],to[MAXM*2+5],nxt[MAXM*2+5],ec;
	void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
}G,T;
void dfs(int x,int f){
	fa[x]=f;vis[x]=1;siz[x]=1;
	for(int e=G.hd[x];e;e=G.nxt[e]){
		int y=G.to[e];if(y==f||vis[y])continue;
		T.adde(x,y);T.adde(y,x);dfs(y,x);
		chkmax(mx[x],siz[y]);siz[x]+=siz[y];
	}
	chkmax(mx[x],n-siz[x]);
	if(mx[x]<mx[cent])cent=x;
}
void dfsT(int x,int f,int col,int &siz){
	if(!x||!siz)return;res[x]=col;--siz;
	for(int e=T.hd[x];e;e=T.nxt[e]){
		int y=T.to[e];if(y==f||res[y])continue;
		dfsT(y,x,col,siz);
	}
}
void dfsG(int x,int f,int col,int &siz){
	if(!x||!siz)return;
	for(int e=T.hd[x];e;e=T.nxt[e]){
		int y=T.to[e];if(y==f)continue;
		dfsG(y,x,col,siz);
	}
	for(int e=G.hd[x];e;e=G.nxt[e]){
		int y=G.to[e];
		if(!res[y]&&y!=cent)dfsT(y,x,col,siz);
	}
}
int main(){
	scanf("%d%d%d%d%d",&n,&m,&A,&B,&C);
	for(int i=1;i<=3;i++)ord[i]=i;
	if(A>B)swap(A,B),swap(ord[1],ord[2]);
	if(A>C)swap(A,C),swap(ord[1],ord[3]);
	if(B>C)swap(B,C),swap(ord[2],ord[3]);
	for(int i=1,u,v;i<=m;i++){
		scanf("%d%d",&u,&v);++u;++v;
		G.adde(u,v);G.adde(v,u);
	}
	mx[0]=INF;dfs(1,0);siz[fa[cent]]=n-siz[cent];
	for(int e=T.hd[cent];e;e=T.nxt[e]){
		int y=T.to[e];
		if(siz[y]>=A){
			dfsT(y,cent,1,A);dfsT(cent,0,2,B);
			for(int i=1;i<=n;i++)printf("%d%c",ord[(!res[i])?3:res[i]]," \n"[i==n]);
			return 0;
		}
	}
	res[cent]=4;
	dfsT(fa[cent],0,1,A);dfsG(fa[cent],cent,1,A);
	if(A){for(int i=1;i<=n;i++)printf("0 ");}
	else{
		dfsT(cent,0,2,B);
		for(int i=1;i<=n;i++)printf("%d%c",ord[(!res[i])?3:res[i]]," \n"[i==n]);
	}
	return 0;
}

标签:IOI2019,子树,洛谷,P5811,siz,int,MAXN,swap,ord
From: https://www.cnblogs.com/tzcwk/p/luogu-P5811.html

相关文章

  • 洛谷P3978 概率论
    首先考虑当节点数为n时,有多少个二叉树设\(f[i]\)表示节点为i时二叉树的个数,有\[f[n]=\sum_{i=1}^{n-1}f[i]f[n-1-i]\]注意这种递推式子也是卡特兰数的一种形式,所以为卡特兰数其实手写出前四项为1,2,5,14我们就要有足够的敏感度知道这是卡特兰数然后考虑叶子个数我们假设我们......
  • 【洛谷 P1305】新二叉树 题解(结构体数组+先序遍历+二叉树)
    新二叉树题目描述输入一串二叉树,输出其前序遍历。输入格式第一行为二叉树的节点数。()后面行,每一个字母为节点,后两个字母分别为其左右儿子。特别地,数据保证第一行读入的节点必为根节点。空节点用*表示输出格式二叉树的前序遍历。样例#1样例输入#16abcbdicj*d**i**j**......
  • 洛谷题解 | AT_abc321_c Primes on Interval
    目录题目翻译题目描述输入格式输出格式样例#1样例输入#1样例输出#1样例#2样例输入#2样例输出#2样例#3样例输入#3样例输出#3题目简化题目思路AC代码题目翻译【题目描述】你决定用素数定理来做一个调查.众所周知,素数又被称为质数,其含义就是除了数字一和本身之外不能......
  • 解题报告 洛谷P2155 [SDOI2008] 沙拉公主的困惑
    P2155[SDOI2008]沙拉公主的困惑题目题面非常的简洁,求\(\sum\limits_{i=1}^{n!}[i\perpm!]\)直接颓式子,\[\begin{aligned}ans&=\dfrac{n!}{m!}\cdot\varphi(m!)\\\\&=\dfrac{n!}{m!}*m!\prod\limits_{p\midm!}[\dfrac{p-1}{p}]\\&=n!\cdot\dfrac{\......
  • 洛谷 P7075[CSP-S2020] 儒略日
    [CSP-S2020]儒略日题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以很方便的......
  • 洛谷 P7075 [CSP-S2020] 儒略日
    P7075[CSP-S2020]儒略日1.题目描述为了简便计算,天文学家们使用儒略日(Julianday)来表达时间。所谓儒略日,其定义为从公元前4713年1月1日正午12点到此后某一时刻间所经过的天数,不满一天者用小数表达。若利用这一天文学历法,则每一个时刻都将被均匀的映射到数轴上,从而得以......
  • 洛谷5249
    先给出一个我自己的不那么套路的做法设p[i][j]表示一共有i个人,第j个人最终幸存的概率那么有\(p[i][j]=\)\[p_{0}*p[i-1][j-1]+(1-p_{0})*p_{0}*p[i-1][j-2]+...+(1-p_{0})^{j-2}*p_{0}*p[i-1][1](即前面j-1个人是否死进行讨论)\]\[+\]\[\]......
  • 洛谷3750 分手是祝愿
    这种可能会有无穷的情况,就是对某一个开关一直按像这种题目我把他叫做无穷型嵌套期望这种题目一般都是用DP推出公式然后化简看着题首先,我们考虑假设最开始最少的操作少于k,应该怎么做很容易发现一个性质,就是按动一个开关,只能影响前面的开关,不能影响后面的开关这是什么?无后效性......
  • Solution of 洛谷-P1896
    并不会有更好的阅读体验\(\text{Sol}\)我们先看一眼数据范围:\(1\leN\le9\)没关系,DFS会出手。好吧,正经的说,如果暴搜的话复杂度会涨到\(\textO(2^{n^2})\),\(\textT\)到飞起。此时我们发现有个东西叫状压\(\text{DP}\),也是解决小范围数据的问题。老套路,枚举每一行,......
  • [洛谷]-5825排列计数-欧拉数、NTT
    目录边界对称性递推形式容斥https://www.luogu.com.cn/problem/P5825题意:我们记一个排列P的升高为\(k\)当且仅当存在\(k\)个位置\(i\)使得\(P_i<P_{i+1}\)。给定排列长度\(n\),对于所有整数\(k\in[0,n]\),求有多少个排列的升高为\(k\),\(1\leqn\leq2\times10^5\)......