CF547D Mike and Fish(图论建模)

题意

二维平面上有 n 个点 (xi,yi),你需要给每个点染色红色或蓝色使得每一行、每一列上红蓝点数差小于等于 1。

n,xi,yi2×105

分析

方法一:上下界网络流

对所有行和列建点,xiyi 连边,流量 [0,1],有流量表示染红。源点向行点连边,流量 [pi2,pi2]pii 行点数,表示染的红点数量必须要在这段区间内与蓝点数量的差才合法。列点向汇点连边,流量同理。

方法二:欧拉回路

可能是一个经典套路。套路性的建行点列点,xi,yi 间连一条无向边。但是这个建模不是很能契合欧拉回路的特征(可能会有奇度点)。不难发现若一行有奇数个点那么两两配对后剩下的点可以随便选,新建一个虚点将所有奇点连向它即可。现在所有点度数为偶,任选起点跑欧拉回路即可,颜色根据边的经过方向定。

方法三:二分图染色

我认为非常优美的思路,我想不到

将一行内的点两两配对,剩下一个点不管。列同理。

可以证明该图为二分图。

感性证明:根据建模,一个点只会跟至多一个与它同横坐标的点和至多一个与它同纵坐标的点连边。假设有点 (x,y)(x,z),yz,由于 (x,z) 已经跟一个横坐标与其相同的点连过边了,那么另一条出边必然和其纵坐标相同,以此类推,当走到与 (x,y) 同侧的点时,其与其入点的纵坐标相同,故若形成奇环,那么这个点一定要和 (x,y) 连边。而 (x,y) 的横坐标边已经跟 (x,z) 相连了,这与一行内点两两匹配的建模方式相悖,因此得证。

给出方法三代码,非常好写:

int n;
vector<int>G[maxn];
int lstx[maxn],lsty[maxn];
int col[maxn];
void dfs(int x,int c){
	col[x]=c;
	for(int u:G[x])if(!col[u])dfs(u,-c);
}
inline void solve_the_problem(){
	n=rd();
	rep(i,1,n){
		int x=rd(),y=rd();
		if(!lstx[x])lstx[x]=i;
		else G[lstx[x]].emplace_back(i),G[i].emplace_back(lstx[x]),lstx[x]=0;
		if(!lsty[y])lsty[y]=i;
		else G[lsty[y]].emplace_back(i),G[i].emplace_back(lsty[y]),lsty[y]=0;
	}
	rep(i,1,n)if(!col[i])dfs(i,1);
	rep(i,1,n)pc(col[i]==1?'r':'b');
}

作者:dcytrl

出处:https://www.cnblogs.com/dcytrl/p/18450669

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   dcytrl  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示