bzoj 2303: [Apio2011]方格染色【并查集】

画图可知,每一行的状态转移到下一行只有两种:奇数列不变,偶数列1;偶数列不变,奇数列1
所以同一行相邻的变革染色格子要放到同一个并查集里,表示这个联通块里的列是联动的
最后统计下联通块数(不包括第一行的这一列已经被染色的情况)快速幂一下即可。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=100005,mod=1e9;
int n,m,k,f[N],fa[N],va[N];
bool mk[N];
struct qwe
{
	int y,c;
	qwe(int Y=0,int C=0)
	{
		y=Y,c=C;
	}
};
vector<qwe>a[N];
int read()
{
	int r=0,f=1;
	char p=getchar();
	while(p>'9'||p<'0')
	{
		if(p=='-')
			f=-1;
		p=getchar();
	}
	while(p>='0'&&p<='9')
	{
		r=r*10+p-48;
		p=getchar();
	}
	return r*f;
}
int ksm(int a,int b)
{
	int r=1;
	while(b)
	{
		if(b&1)
			r=1ll*r*a%mod;
		a=1ll*a*a%mod;
		b>>=1;
	}
	return r;
}
int zhao(int x)
{
	return fa[x]==x?x:fa[x]=zhao(fa[x]);
}
int find(int x)
{
	if(x==f[x])
		return x;
	int now=find(f[x]);
	va[x]^=va[f[x]];
	return f[x]=now;
}
bool ok(int x,int y,int p)
{
	int fx=find(x),fy=find(y);
	if(fx!=fy)
	{
		f[fx]=fy;
		va[fx]=va[x]^va[y]^p;
	}
	else if((va[x]^va[y])!=p)
		return 0;
	return 1;
}
int main()
{
	n=read(),m=read(),k=read();
	for(int i=1;i<=k;i++)
	{
		int x=read(),y=read(),c=read();
		a[x].push_back(qwe(y,c));
		if(x==1)
			mk[y]=1;
	}
	for(int i=1;i<=m;i++)
		f[i]=fa[i]=i;
	for(int i=1;i<=n;i++)
		for(int j=1;j<a[i].size();j++)
		{
			int x=a[i][j-1].y,y=a[i][j].y,fx=zhao(x),fy=zhao(y);
			fa[fx]=fy;
			if(mk[fx])
				mk[fy]=1;
			int p=a[i][j-1].c^a[i][j].c;
			if((x&1)!=(y&1))
				p^=(i-1)&1;
			if(!ok(x,y,p))
			{
				puts("0");
				return 0;
			}
		}
	int ans=0;
	for(int i=2;i<=n;i++)
		if(!a[i].size())
			ans++;
	for(int i=1;i<=m;i++)
		if(fa[i]==i&&!mk[i])
			ans++;
	printf("%d\n",ksm(2,ans));
	return 0;
}
posted @ 2018-04-15 09:31  lokiii  阅读(221)  评论(0编辑  收藏  举报