zoukankan      html  css  js  c++  java
  • CF1567F OneFour Overload 题解

    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;
    }
    
  • 相关阅读:
    influxdb时序数据库之随想其他列式存储数据库
    ss 命令参数 redis-benchmark 以及POSTMAN, CURL分析网络
    HTTP2.0
    我的2020工作总结
    2021-03-31 JDK8 字符串常量池
    try catch与spring的事务回滚
    Spring主动触发事务回滚
    Redis五种数据类型及应用场景
    java面试题
    ubuntu linux mysql 安装 基本操作 命令
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15251461.html
Copyright © 2011-2022 走看看