当前位置: 首页 > article >正文

P3631 [APIO2011] 方格染色

      ~~~~~      P3631 [APIO2011] 方格染色       ~~~~~      总题单链接

思路

      ~~~~~       1 1 1表示红色, 0 0 0 表示蓝色, c o l [ i ] [ j ] col[i][j] col[i][j] 表示第 i i i 行,第 j j j 列的颜色。发现 i ≥ 2 , j ≥ 2 i\geq 2,j\geq 2 i2,j2 时, c o l [ i ] [ j ] = c o l [ i − 1 ] [ j − 1 ] ⊕ c o l [ i − 1 ] [ j ] ⊕ c o l [ i ] [ j − 1 ] ⊕ 1 col[i][j] = col[i-1][j-1]\oplus col[i-1][j]\oplus col[i][j-1]\oplus 1 col[i][j]=col[i1][j1]col[i1][j]col[i][j1]1,所以只要第一行和第一列的颜色确定了,整个矩阵就能确定。

      ~~~~~      但这还不够,先不管 ⊕ 1 \oplus 1 1 画个图看一下:

      ~~~~~      发现 a [ i ] [ j ] = a [ 1 ] [ 1 ] ⊕ a [ i ] [ 1 ] ⊕ a [ 1 ] [ j ] a[i][j]=a[1][1]\oplus a[i][1]\oplus a[1][j] a[i][j]=a[1][1]a[i][1]a[1][j],所以每次涂色等同于一个形如一个(若第 i i i行第一列的值是 a a a,则第 j j j 列第一行的值是 b b b)的限制,这里的 a , b ∈ { 0 , 1 } a,b \in{\{0,1\}} a,b{0,1},欸,那么 a [ 1 ] [ 1 ] a[1][1] a[1][1] 去哪了,仔细想想,假如这条限制默认 a [ 1 ] [ 1 ] = 0 a[1][1]=0 a[1][1]=0,那 a [ 1 ] [ 1 ] = 1 a[1][1]=1 a[1][1]=1 的情况不就是把 a , b a,b a,b 换一下吗,所以 a [ 1 ] [ 1 ] a[1][1] a[1][1] 在这条限制中其实不重要。

      ~~~~~      那么大概就可以往连边和连通块的方向去想了。

      ~~~~~      将每行每列视为两个点 u 0 u_0 u0 u 1 u_1 u1,表示这一行 / / /列的第一个值选 0 / 1 0/1 0/1

      ~~~~~      对于一次在第 i i i 行,第 j j j 列,颜色为 c c c 的涂色,设 u 0 , u 1 u_0,u_1 u0,u1 表示第 i i i 行表示的两个点, v 0 , v 1 v_0,v_1 v0,v1 表示第 j j j 列表示的两个点,连两条边 u 0  ——  v c , u 1  ——  v c ⊕ 1 u_0~——~v_c,u_1~——~v_{c\oplus 1} u0 —— vc,u1 —— vc1,连边后一个连通块就必须要一起选了,如果存在一个点使得 u 0 , u 1 u_0,u_1 u0,u1 在一个连通块中,那么答案就是 0 0 0

      ~~~~~      我们还没有考虑 ⊕ 1 \oplus 1 1,再画一个只考虑 ⊕ 1 \oplus 1 1的图:

      ~~~~~      发现只有 i , j i,j i,j 都为偶数的情况下才会 ⊕ 1 \oplus 1 1,直接将 c ⊕ 1 c\oplus 1 c1即可。

      ~~~~~      我个人认到这里还是比较难理解的,我也想了很久,所以如果你没有理解大可不必着急,慢慢来,再看一遍或者自己动手画图,模拟一下样例。

代码

#include<bits/stdc++.h>
#define ll long long
#define MOD 1000000000
using namespace std;

inline ll qmi(ll a,ll b){
	ll res=1;
	while(b){
		if(b&1)(res*=a)%=MOD;
		(a*=a)%=MOD;b>>=1;
	}
	return res;
}

ll n,m,Q;

inline ll U(ll x,ll y){return(y==0?x:x+n);} 
inline ll V(ll x,ll y){return(y==0?x+n*2:x+n*2+m);}

struct BJ{
	ll fas[400005],cnt;
	void init(){for(ll i=1;i<=2*(n+m);i++)fas[i]=i;cnt=2*(n+m);}
	inline ll fid(ll p){
		if(fas[p]!=p)fas[p]=fid(fas[p]);
		return fas[p];
	}
	inline void uni(ll x,ll y){
		x=fid(x),y=fid(y);
		if(x!=y)fas[x]=y,cnt--;
	}
}bj;

signed main(){
	ios::sync_with_stdio(false);
	
	cin>>n>>m>>Q;
	if(n==1||m==1){
		cout<<qmi(2,n*m-Q);
		return 0;
	}
	
	bj.init();
	
	ll opt=1;
	while(Q--){
		ll x,y,c;
		cin>>x>>y>>c;
		if(x%2==0&&y%2==0)c^=1;
		bj.uni(U(x,0),V(y,c));
		bj.uni(U(x,1),V(y,c^1));
		if(bj.fid(U(x,0))==bj.fid(U(x,1))||bj.fid(V(y,0))==bj.fid(V(y,1)))opt=0;
	}
	cout<<(opt==1?qmi(2,bj.cnt/2-1):0)<<endl;
	
	return 0;
}

      ~~~~~      侵权必 … \ldots 算了都没人看,哪来的侵权。考虑给个赞和关注吗?


http://www.kler.cn/a/291682.html

相关文章:

  • springboot上传下载文件
  • 七、箭头函数及简写、arguments、剩余参数、展开运算符、解构数组与对象、数组常见方法(forEach、map、join、reduce)
  • 什么是JSX?
  • 【MySQL】RedHat8安装mysql9.1
  • 【.NET 8 实战--孢子记账--从单体到微服务】--简易权限--完善TODO标记的代码
  • 结构化需求分析与设计
  • 深度学习速通系列:Bert模型vs大型语言模型(LLM)
  • 【前端面试】采用react前后,浏览器-解析渲染UI的变化
  • 解决jupyter notebook启动需要密码的问题
  • Zabbix_Proxy自动化安装脚本
  • 五分钟搭建微信机器人保姆级教程
  • SSG页面加上了 revalidate,是不是就变成了 ISG?
  • WebRTC协议下的视频汇聚融合技术:EasyCVR视频技术构建高效视频交互体验
  • python-Flask搭建简易登录界面
  • Java 7.3 - 分布式 id
  • linux——进程
  • v$session_longops监控 PDB clone 进度
  • Elasticsearch在高并发下如何保证读写一致性
  • Git创建项目
  • 一款云笔记支持在线协同文档,脑图,白板演示的工具,多个设备同步,让灵感与你同行(附源码)
  • 深度学习实战3--GAN:基础手写数字对抗生成
  • HarmonyOS开发实战( Beta5版)不要使用函数/方法作为复用组件的入参规范实践
  • 基于vue框架的车辆交易管理系统n5xwr(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
  • day17JS-Cookle、webStorage和Promise
  • Day22_K8S
  • 使用GPU加速及配置