您的位置:首页 > 其它

[Apio2011]方格染色

2014-12-29 08:20 246 查看
Time Limit: 20
Sec  Memory
Limit: 256 MB

Description

Sam和他的妹妹Sara有一个包含n × m个方格的

表格。她们想要将其的每个方格都染成红色或蓝色。

出于个人喜好,他们想要表格中每个2 ×   2的方形区

域都包含奇数个(1 个或 3 个)红色方格。例如,右

图是一个合法的表格染色方案(在打印稿中,深色代

表蓝色,浅色代表红色) 。

可是昨天晚上,有人已经给表格中的一些方格染上了颜色!现在Sam和Sara

非常生气。不过,他们想要知道是否可能给剩下的方格染上颜色,使得整个表格

仍然满足她们的要求。如果可能的话,满足他们要求的染色方案数有多少呢?

Input

输入的第一行包含三个整数n, m和k,分别代表表格的行数、列数和已被染

色的方格数目。

之后的k行描述已被染色的方格。其中第 i行包含三个整数xi, yi和ci,分别

代表第 i 个已被染色的方格的行编号、列编号和颜色。ci为 1 表示方格被染成红

色,ci为 0表示方格被染成蓝色。

Output

输出一个整数,表示可能的染色方案数目 W 模 10^9得到的值。(也就是说,如果 W大于等于10^9,则输出
W被10^9除所得的余数)。

对于所有的测试数据,2 ≤ n, m ≤ 106

,0 ≤ k ≤ 10^6

,1 ≤ xi ≤ n,1 ≤ yi ≤ m。

Sample Input

3 4 3

2 2 1

1 2 0

2 3 1

Sample Output

8
 
 
题解:1.BFS
2.并查集(类似10年NOIP第三题)
 

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
假设这是一张4×4的表格。根据题意,任意一个2×2的格子内的四个数的异或值为1。所以A^B^E^F=1,B^F^C^G=1.
两式异或。则A^E^C^G=0. 同理,A^E^D^H=1. 

又,A^B^E^F=1, E^F^I^J=1. 所以A^B^I^J=0.

又,F^G^J^K=1,E^F^I^J=1,A^E^C^G=0.
所以,A^C^I^K=0.     
(^符号表示异或运算)

综上,对于表格中的任意一个不在第一行且不在第一列的格子的颜色都由该格所在行与列的第一个数与左上角的数的异或值决定。即c[i,j]=c[1,j]
xor c[i,1] xor c[1,1].

所以,当表格的第一行与第一列的值都固定后,整张表格就唯一确定了。

而左上角的格子颜色只有两种,所以我们可以枚举其颜色,然后每个格子就只由行首与列首两个格子决定了。

假设一开始表格的第一行和第一列都为零,则形如:

 

0
0
0
0
0
0
0
0
1
0
1
0
1
0
0
0
0
0
0
0
0
0
1
0
1
0
1
0
0
0
0
0
0
0
0
0
1
0
1
0
1
0
0
0
0
0
0
0
0
 

则对于每一个c[i,j],若i与j同为偶数时,它的颜色为1,则行列的首格的异或值为0,颜色为0,则行列的首格的异或值为1。若i与j不同时为偶数,它的颜色为1,则行列的首格的异或值为1,颜色为0,则行列的首格的异或值为0。

由此,对读入的每一个确定颜色的格子,都可以确定它的行列首格的关系(相同或不同;异或值为0或为1)。

操作时对于修改首行或首列的格子时,我的做法是建立一个数组记录每个节点的颜色,然后修改这个格子父亲的颜色,有冲突即无解。还有两个格子有同一个父亲,可是原关系与所给关系冲突也是无解的情况。

剩下的就是并查集的基本操作了。路径压缩时修改与父亲的关系。

如果输入给定了左上角的颜色,那么如果颜色为1,则将读入颜色全部取反做一遍,如果颜色为0,则只要做一遍,没有给出颜色则枚举颜色做两遍。将两次的方案数相加。

最后方案数的求法就是2的未被染色的集合个数的次方。。就是2^(未被染色的集合个数)。这是建立在有解的前提下的。。

 

AC
CODE


 

//又臭又长。。。

 

program

hy_2303;

const

mo=
1000000000
;

var

h,l,c,fa,co,re:
array
[
1..1000000
]

of
longint
;

    
p:
array
[
1..1000000
]

of
boolean
;

    
n,m,k,i,ans,tt:
longint
;

    
flagg:
boolean
;

//===============================
4000
=============================================

function

getfa(x:
longint
):
longint
;

begin

  
if

fa[x]=x
then
exit(x);

  
getfa:=getfa(fa[x]);

  
re[x]:=re[x]

xor
re[fa[x]];

  
fa[x]:=getfa;

end
;

//============================================================================

procedure

march;

var

i,fx,fy,x,y,z,tmp:
longint
;

    
flag:
boolean
;

begin

  
for

i:=
1
to

n+m-
2
do

  
begin

    
fa[i]:=i;
co[i]:=-
1
; re[i]:=
0
;

  
end
;
flag:=
true
;

  
for

i:=
1
to

k
do

  
begin

    
if

(l[i]=
1
)

and
(h[i]=
1
)

then
continue;

    
if

l[i]=
1
then  //在第一列。

    
begin

      
z:=m-
1
+h[i]-
1
;

      
fx:=getfa(z);

      
if

co[fx]=-
1
then

co[fx]:=c[i]
xor
re[z]

else 
//未被染色,修改颜色。

        
if

co[fx]
xor
re[z]<>c[i]

then 
//已染色,判断是否冲突。

        
begin

flag:=
false
;
break;
end
;

      
continue;

    
end

else

    
if

h[i]=
1
then  //在第一行。

    
begin

      
z:=l[i]-
1
;

      
fx:=getfa(z);

      
if

co[fx]=-
1
then

co[fx]:=c[i]
xor
re[z]

else 
//未被染色,修改颜色。

        
if

co[fx]
xor
re[z]<>c[i]

then 
////已染色,判断是否冲突。

        
begin

flag:=
false
;
break;
end
;

      
continue;

    
end
;

    
x:=m-
1
+h[i]-
1
;
y:=l[i]-
1
;

    
fx:=getfa(x);

    
fy:=getfa(y);

    
if

(h[i]
mod
2
=
0
)

and
(l[i]
mod

2
=
0
)

then

    
begin

      
if

c[i]=
1
then

      
begin

        
if

(fx=fy)
and
(re[x]
xor
re[y]<>
0
)

then

        
begin

flag:=
false
;
break;
end
;

        
re[fx]:=re[x]

xor
re[y];

        
fa[fx]:=fy;

        
if

co[fx]>-
1
then 
//合并两个集合的时候也要将颜色带上。。

        
begin

          
if

co[fy]=-
1
then

co[fy]:=co[fx]
xor
re[fx]
else

          
if

co[fy]<>co[fx]

xor
re[fx]
then

          
begin

flag:=
false
;
break;
end
;

        
end
;

      
end

else

      
begin

        
if

(fx=fy)
and
(re[x]
xor
re[y]<>
1
)

then

        
begin

flag:=
false
;
break;
end
;

        
re[fx]:=re[x]

xor
re[y]
xor

1
;

        
fa[fx]:=fy;

        
if

co[fx]>-
1
then 
//合并两个集合的时候也要将颜色带上。。

          
if

co[fy]=-
1
then

co[fy]:=co[fx]
xor
re[fx]
else

          
if

co[fy]<>co[fx]

xor
re[fx]
then

          
begin

flag:=
false
;
break;
end
;

      
end
;

    
end

else

    
begin

      
if

c[i]=
1
then

      
begin

        
if

(fx=fy)
and
(re[x]
xor
re[y]<>
1
)

then

        
begin

flag:=
false
;
break;
end
;

        
re[fx]:=re[x]

xor
re[y]
xor

1
;
fa[fx]:=fy;

        
if

co[fx]>-
1
then

          
if

co[fy]=-
1
then

co[fy]:=co[fx]
xor
re[fx]
else

          
if

co[fy]<>co[fx]

xor
re[fx]
then

          
begin

flag:=
false
;
break;
end
;

      
end

else

      
begin

        
if

(fx=fy)
and
(re[x]
xor
re[y]<>
0
)

then

        
begin

flag:=
false
;
break;
end
;

        
re[fx]:=re[x]

xor
re[y]; fa[fx]:=fy;

        
if

co[fx]>-
1
then

          
if

co[fy]=-
1
then

co[fy]:=co[fx]
xor
re[fx]
else

          
if

co[fy]<>co[fx]

xor
re[fx]
then

          
begin

flag:=
false
;
break;
end
;

      
end
;         
//话说这里粘贴了4个几乎一样的。。代码量暴涨。。。

    
end
;

  
end
;

  
if

not
(flag)
then
exit;

  
for

i:=
1
to

n+m-
2
do

p[i]:=
false
;

  
tmp:=
1
;

  
for

i:=
1
to

n+m-
2
do

  
begin

    
fx:=getfa(i);

    
if

not
(p[fx])
and
(co[fx]=-
1
)

then

    
begin

      
tmp:=(tmp*
2
)

mod
mo;

      
p[fx]:=
true
;

    
end
;

  
end
;

  
ans:=(ans+tmp)

mod
mo;

end
;

//============================================================================

begin

  
readln(n,m,k);
flagg:=
false
;

  
for

i:=
1
to

k
do

  
begin

    
readln(h[i],l[i],c[i]);

    
if

(l[i]=
1
)

and
(h[i]=
1
)

then

    
begin

      
flagg:=
true
;
tt:=c[i];

    
end
;

  
end
;

  
if

flagg
and
(tt=
1
)

then

    
for

i:=
1
to

k
do
c[i]:=c[i]
xor
1
;

  
march;

  
if

not
(flagg)
then

  
begin

    
for

i:=
1
to

k
do
c[i]:=c[i]
xor
1
;

    
march;

  
end
;

  
writeln
(ans);

end
.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: