首页 > 其他分享 >[IOI2019] 景点划分

[IOI2019] 景点划分

时间:2024-04-25 17:15:54浏览次数:24  
标签:rt IOI2019 le int siz mxv 划分 maxn 景点

令人忍俊不禁的是,11 月的模拟赛出现了 “摩拉克斯” 一题,被取之。2 月 JOISC 出现这个模型,被取之。2 月模拟赛出现这个模型,被取之。本题再次出现这个模型,被取之。

呃呃呃呃呃呃呃呃呃啊。

首先进行一些简单的分析:令 \(A\le B\le C\),构造 \(A,B\) 合法的情况即可。并且有 \(A\le n/3, B\le n/2\)。

直接做似乎不好做,从树的情况入手。

树上连通块划分:存在一条边使得两个划分的连通块分别在其两侧。

此时直接枚举已经可以做了,但是这个做法我不好搬到图上啊,仔细分析一番。

我觉得接下来的分析有点不自然,然而似乎是常用思路:注意到两个连通块必然有一个包含原树的重心,以重心为根,如果割掉 \((x,fa_x)\) 的方案合法,那么假设 \(x\) 所在的根的子树为 \(y\),则割掉 \((y,rt)\) 合法。

于是把重心拿出来判断即可,如果所有子树都 \(<A\) 直接就寄了,否则有 \(A\le sz_x\le n/2\),则 \(n-sz_x\ge n/2\ge B\),于是得出判定条件和构造方法,这个就比较漂亮了。

回到原题,自然地想到拿出 DFS 树的重心进行考察,假设子树为 \(s_1,s_2,\dots ,s_k\),父亲为 \(T\)。

首先执行上述树的构造,如果无解则 \(\forall i\in [1,k], |s_i|\le A\) 且 \(|T|\le A\)。

由于 DFS 树的性质,会有一些边将 \(s\) 和 \(T\) 相连。如果这些 \(s\) 和 \(T\) 拼起来都不行就还是寄了,否则选几个 \(s\) 和 \(T\) 拼起来,使得 \(A\le siz\le 2A\),又因为 \(2A+B\le A+B+C=n\) 所以剩下的部分可以凑出一个 \(B\)。问题得到了解答。

感觉是挺漂亮的题目,从树的情况出发,自然的通过 DFS 树搬到图上,并且运用了代数上的简单处理。

放一下代码,感觉我写的还行,只有 2.4k。

#include <bits/stdc++.h>
#define pb emplace_back
#define fir first
#define sec second

using i64 = long long;
using pii = std::pair<int, int>;

constexpr int maxn = 1e5 + 5;
int A, B, n, m, fa[maxn], siz[maxn], mxv[maxn], bel[maxn], rt, dep[maxn], low[maxn];
std::vector<int> G[maxn], E[maxn];

void chkmax(int& x, int y) { if (y > x) x = y; return ; }
void chkmin(int& x, int y) { if (y < x) x = y; return ; }

void dfs(int u, int ff) {
	fa[u] = ff;
	dep[u] = dep[ff] + 1;
	low[u] = dep[u];
	siz[u] = 1;
	mxv[u] = 0;
	for (auto& v : G[u]) {
		if (dep[v]) {
			chkmin(low[u], dep[v]);
			continue ;
		}
		dfs(v, u);
		siz[u] += siz[v];
		E[u].pb(v);
		chkmin(low[u], low[v]);
		chkmax(mxv[u], siz[v]);
	}
	if (ff) E[u].pb(ff);
	chkmax(mxv[u], n - siz[u]);
	if (mxv[u] < mxv[rt]) rt = u;
	return ;
}

bool ban[maxn];

void dfs2(int u, int ff, int& res, int typ) {
	if (!res) return ;
	--res;
	bel[u] = typ;
	for (auto& v : E[u]) {
		if (v == ff || ban[v]) continue ;
		dfs2(v, u, res, typ);
		if (!res) return ;
	}
	return ;
}

int Nosol() {
	for (int i = 1; i <= n; ++i)
		std::cout << "0 ";
	return std::cout << "\n", 0;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr); std::cout.tie(nullptr);
	std::cin >> n >> m;
	std::vector<std::pair<int, int>> qry(3);
	for (int i = 0; i < 3; ++i)
		std::cin >> qry[i].fir, qry[i].sec = i + 1;
	std::sort(qry.begin(), qry.end());
	A = qry[0].fir;
	B = qry[1].fir;
	for (int i = 1; i <= m; ++i) {
		int u, v;
		std::cin >> u >> v;
		++u;
		++v;
		G[u].pb(v);
		G[v].pb(u);
	}
	mxv[0] = 114514;
	dfs(1, 0);
	std::fill(bel + 1, bel + 1 + n, 2);
	if (mxv[rt] >= A) {
		int pos = 0;
		ban[rt] = true;
		for (auto& v : E[rt]) {
			int sz = v == fa[rt] ? n - siz[rt] : siz[v];
			if (sz >= A) {
				dfs2(v, 0, A, 0);
				pos = v;
				break ;
			}
		}
		ban[rt] = false;
		ban[pos] = true;
		dfs2(rt, 0, B, 1);
	} else {
		std::vector<int> g;
		int tot = n - siz[rt];
		for (auto& v : E[rt]) {
			if (v == fa[rt] || low[v] >= dep[rt]) continue ;
			g.pb(v);
			tot += siz[v];
		}
		if (tot < A) return Nosol();
		ban[rt] = true;
		if (fa[rt]) {
			dfs2(fa[rt], 0, A, 0);
			ban[fa[rt]] = true;
		}
		for (auto& v : g) {
			if (A <= 0) break ;
			dfs2(v, 0, A, 0);
			ban[v] = true;
		}
		ban[rt] = false;
		dfs2(rt, 0, B, 1);
	}
	for (int i = 1; i <= n; ++i)
		std::cout << qry[bel[i]].sec << ' ';
	return 0;
}

标签:rt,IOI2019,le,int,siz,mxv,划分,maxn,景点
From: https://www.cnblogs.com/663B/p/18158113

相关文章

  • 马蜂窝景点评论(以恭王府为例)
    1.python部分马蜂窝.py#-*-coding:utf-8-*-#@Time:2024/04/1518:34#@Author:快乐的小猴子#@Version:#@Function:importsubprocessfromfunctoolsimportpartialsubprocess.Popen=partial(subprocess.Popen,encoding='utf-8')importexecjsimpo......
  • 07、VXLAN网关划分
    VXLAN网关划分和VLAN类似,不同VNI之间的VXLAN,及VXLAN和非VXLAN之间不能直接相互通信。为了使VXLAN之间,以及VXLAN和非VXLAN之间能够进行通信,VXLAN引入了VXLAN网关。VXLAN网关分为:二层网关:用于解决租户接入VXLAN虚拟网络的问题,也可用于同一VXLAN虚拟网络的子网通信。三层网......
  • mtk相机冷启动阶段划分
     如上图:s0:手指抬起到app创建的时间s1:app创建完成到下发opencamera的时间s2:hal接受到app打开相机消息,connectdevice,给sensor上电,并回调告诉app硬件已经连接成功了s3:app接受到hal的回调之后,认为hal已经准备好了,就创建会话准备进行图像上传s4:hal接受到app已经创......
  • 字节面试:领域、子域、核心域、通用域和支撑域怎么划分?
    领域驱动设计(DDD)里面有一堆专业术语,比如领域、子域、核心域、通用域、支撑域等等,听着是不是觉得挺吓人?别怕,我来带你轻松搞懂它们。如何理解领域和子域?领域是指一定的业务范围或问题域。在解决业务问题时,DDD会将业务领域进行细分,将问题范围限定在一定的边界内,在这个边界内建立领......
  • 【二分+容斥】【ST表/单调栈】【划分型DP】
    二分+容斥题目链接https://leetcode.cn/problems/kth-smallest-amount-with-single-denomination-combination/description/题目大意题目思路假设有一个x元硬币思考只有一种面额为3的硬币时,3可以组成不超过x的面额的数量有x/3种!思考有两种面额【3,6】,可以组成不......
  • 子网划分
    概念IP地址是以网络号和主机号来表示网络上的主机的,只有在一个网络号下的计算机之间才能“直接”互通,不同网络号的计算机要通过网关(Gateway)才能互通。但这样的划分在某些情况下显得并不十分灵活。为此IP网络还允许划分成更小的网络,称为子网(Subnet)。在线网络计算器https://......
  • 【交换机】华三交换机端口加入vlan命令_h3c交换机vlan配置划分命令
    h3c交换机vlan配置划分命令一、基本设置1.console线连接成功2.进入系统模式system-view//提示符由变为[H3C]3.更改设备名称[H3C]sysnameTEST4.查看所有配置信息[H3C]displaycurrent-configuration//displaythis为查看当前路径下的设备信息5.创建并进入VLAN......
  • 2-48. 实现鼠标选中物品后的场景点击事件流程
    修改CursorManager修改EventHandler修改Player修改GridMapManager继续修改CursorManager继续修改EventHandler我们希望人物扔出东西的时候,不是直接在地面上生成一个物品,而是有一个扔的效果修改ItemManager修改InventoryManager继续修改GridMapMa......
  • 实验:基于Red Hat Enterprise Linux系统建立逻辑卷并进行划分
    目录一.实验目的二.实验内容三.实验设计描述及实验结果    1.为虚拟机添加三块大小为5GB的磁盘nvme0n2 nvme0n3 nvme0n4    2.将三块硬盘转换为物理卷,并将nvme0n2 nvme0n3两pv建立成名为"自己名字_vg“的卷组,并将nvme0n4扩展进该卷组。    ......
  • [POI2007] [LUOGU P3451]旅游景点 Tourist Attractions
    本题解由于作者太菜在POI及LUOGU上会TLE,该题解主要讲思路,剩下的内存优化请各位大佬自行补充,欢迎评论区讨论本题解运行时间10406ms,空间194584KiB题目描述FGD想从成都去上海旅游。在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情。经过这些城......