ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1567F One-Four Overload 题解

2021-09-10 15:34:27  阅读:227  来源: 互联网

标签:cl int 题解 直边 网格 Four read Leftrightarrow CF1567F


Codeforces
Luogu

P.S.

给个证明?

Description.

给定一个 \(n\times m\) 的矩阵,每个元素是 X.
共两种颜色,对每个 . 染上一种颜色,使得所有 X 周围不同颜色出现次数相同。

Solution.

对于一个 X 周围有奇数个 . 的情况,显然直接无解。
一个 X 周围有 \(0\) 个 .,显然不用考虑。
一个 X 周围有 \(2\) 个 .,一个是黑另一个就是白,直接二分图染色即可。
一个 X 周围有 \(4\) 个 .,有点麻烦。

结论是一个 X 周围有 \(4\) 个 . 时。
钦定 \((x-1,y)\Leftrightarrow(x,y-1)\) 和 \((x+1,y)\Leftrightarrow(x,y+1)\) 即可。

证明如下:
证明原结论,只需要证明这样构造不存在奇环即可。
用反证法:假设有奇环。
首先,有两种边,第一种是 \((x,y)\Leftrightarrow(x\pm1,y\pm1)\) 的边,称为斜边。
第二种是 \((x,y)\Leftrightarrow(x\pm2,y)\) 或 \((x,y)\Leftrightarrow(x,y\pm2)\) 的边,称为直边。
定义一个坐标的奇偶性为它横坐标的奇偶性。
那斜边会改变一个坐标的奇偶性,而直边不会。
因为成环,所以起点终点坐标和奇偶性相同。
所以肯定有偶数调斜边,那就有奇数条直边。
考虑如果存在了一条直边,那直边两点中间至少存在长度为 \(3\) 的连续 X
然后最旁边的两个 X 周围有 \(3\) 个 .,然后会继续往旁边扩展。
同时两刀是不能合并成同一刀的,那样会出现一个格子是奇数。
脑补一下这个长什么样,显然就是把原图切成了网格。
每个网格的边缘可以通过一个空心闭合宽为 \(1\) 的截。
产生了两个,但是其实并不会影响,因为走进去不管在那边都还需要走出来。
每条直边是一个连接两个网格的边。
所以从一个网格走回这个网格会跨过偶数个边界。
与环上有奇数条直边矛盾。
所以它肯定是二分图。

Coding.

点击查看太菜代码
//是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
template<typename T>inline void read(T &x)
{
	x=0;char c=getchar(),f=0;
	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
	f?x=-x:x;
}
template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
const int dx[4]={-1,0,1,0},dy[4]={0,-1,0,1};
int n,m,cl[250005],vv[505][505];char ch[505][505];
struct edge{int to,nxt;}e[500005];int et,head[250005];
inline void adde(int x,int y) {e[++et]=(edge){y,head[x]},head[x]=et;}
#define ID(i,j) ((i-1)*m+(j))
inline void dfs(int x)
{
	for(int i=head[x];i;i=e[i].nxt)
		if(!~cl[e[i].to]) cl[e[i].to]=cl[x]^1,dfs(e[i].to);
		else if(!(cl[x]^cl[e[i].to])) puts("NO"),exit(0);
}
int main()
{
	read(n,m);for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(ch[i][j]=='X')
	{
		vector<int>v;int cnt=0;for(int k=0;k<4;k++)
		{
			int nx=i+dx[k],ny=j+dy[k];
			if(nx<1||nx>n||ny<1||ny>m) continue;
			if(ch[nx][ny]=='.') cnt++,v.push_back(ID(nx,ny));
		}
		if(cnt&1) return puts("NO"),0;else vv[i][j]=cnt/2*5;
		for(int i=0;i<(int)v.size();i+=2) adde(v[i],v[i+1]),adde(v[i+1],v[i]);
	}
	memset(cl,-1,sizeof(cl));for(int i=1;i<=n*m;i++) if(!~cl[i]) cl[i]=0,dfs(i);
	puts("YES");for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
		printf("%d%c",ch[i][j]=='X'?vv[i][j]:cl[ID(i,j)]?4:1,j==m?'\n':' ');
	return 0;
}

标签:cl,int,题解,直边,网格,Four,read,Leftrightarrow,CF1567F
来源: https://www.cnblogs.com/pealfrog/p/15251461.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有