CF1844E. Great Grids

題目大意

有一個n*m的網格圖,需要在每個格子內部填入A~C,要求滿足:

① 每個2*2的小方格都要有ABC
② 邊相鄰格子內字母不同

給出初始若干格子相同(滿足角相鄰)的限制,判斷是否存在合法解

2<=n,m<=2e3

題解

神必題……

首先假設給2*2的格子內角相鄰的相同格子連斜邊,則會連出一個圖,每個2*2格子內都要有一條連邊

然後在這個圖裏連通的都是同一個字母,所以會有一些連邊情況不合法,比如

這樣,則實際上外面四個圓圈都相等,所以會連一下,與右上的邊衝突

顯然所有連邊同向合法,然後根據觀察可得,將一個合法圖的斜邊進行任意行/列翻轉仍然合法

所以可以根據行/列是否翻轉設01狀態,然後用給出的限制來對行/列狀態連邊(相同/相異),最後dfs判斷是否有矛盾即可

證明:
可以設ABC對應012,然後對邊相鄰的格子連橫向/縱向的邊,邊權爲(上-下)%3 or (左-右)%3

然後觀察發現一個2*2格子內,上下和左右的邊權分別相等(確定一行/列的狀態,只能是1/2),且當正對角線相同時上下=左右,反對角線相同時上下≠左右

把差值1/2變成0/1,設爲行/列的權值;兩種邊決定行列權值相同/相異,則和上面差不多了

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
#define file
using namespace std;
 
int T,n,m,K,i,j,k,l,x,y;
int X1,Y1,X2,Y2;
int a[80001][3],ls[40001],len;
int f[40001];
bool ans;
 
void New(int x,int y,int z)
{
	++len;
	a[len][0]=y;
	a[len][1]=ls[x];
	ls[x]=len;
	a[len][2]=z;
}
 
void dfs(int t)
{
	int i;
	
	for (i=ls[t]; i; i=a[i][1])
	if (f[a[i][0]]==-1)
	{
		f[a[i][0]]=f[t]^a[i][2];
		dfs(a[i][0]);
	}
	else
	if (f[a[i][0]]!=(f[t]^a[i][2]))
	ans=0;
}
 
int main()
{
	scanf("%d",&T);
	for (;T;--T)
	{
		len=0;
		scanf("%d%d%d",&n,&m,&K);
		fo(i,1,n+m) f[i]=-1,ls[i]=0;
		
		fo(i,1,K)
		{
			scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
			
			x=min(X1,X2);
			y=min(Y1,Y2);
			if (x==X1 && y==Y1 || x==X2 && y==Y2) //1
			{
				New(x,n+y,0);
				New(n+y,x,0);
			}
			else //2
			{
				New(x,n+y,1);
				New(n+y,x,1);
			}
		}
		
		ans=1;
		fo(i,1,n+m)
		if (f[i]==-1)
		f[i]=0,dfs(i);
		
		if (ans)
		cout<<"YES"<<endl;
		else
		cout<<"NO"<<endl;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章