zoukankan      html  css  js  c++  java
  • BZOJ2303:[APIO2011]方格染色(并查集)

    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

    Solution 

    这个题真的神仙……
    首先可以发现若方案合法,相邻四个格子的数字异或和为1.
    由这个我们可以从格子$(1,1)$往右下角推,然后得出一个结论,若行和列都是偶数,$1xor(1,1)xor(i,j)=(1,j)xor(i,1)$
    否则$(1,1)xor(i,j)=(1,j)xor(i,1)$。
    那么对于每一个给出格子,他可以确定该行首和该列首的两个格子的关系。
    若$(1,1)$格子未被确定,则枚举两个颜色然后去做。
    剩下的就可以用加权并查集判断是否合法了……

    Code

     1 #include<iostream>
     2 #include<cstdio>
     3 #define N (200009)
     4 #define MOD (1000000000)
     5 using namespace std;
     6 
     7 int n,m,k,ans,flag[2]={1,1};
     8 int x[N],y[N],c[N],fa[N],g[N];
     9 
    10 int Find(int x)
    11 {
    12     if (x==fa[x]) return x;
    13     int f=Find(fa[x]);
    14     g[x]^=g[fa[x]]; return fa[x]=f;
    15 }
    16 
    17 int Calc()
    18 {
    19     for (int i=1; i<=n+m; ++i) fa[i]=i,g[i]=0;
    20     fa[1+n]=1;
    21     for (int i=1; i<=k; ++i)
    22     {
    23         int fx=Find(x[i]),fy=Find(y[i]+n);
    24         int temp=g[x[i]]^g[y[i]+n]^c[i];
    25         if (fx!=fy) fa[fx]=fy,g[fx]=temp;
    26         else if (temp) return 0;
    27     }
    28     int ans=-1;
    29     for (int i=1; i<=n+m; ++i)
    30         if (fa[i]==i)
    31         {
    32             if (ans==-1) ans=1;
    33             else ans<<=1;
    34             if (ans>=MOD) ans-=MOD;
    35         }
    36     return ans;
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%d%d%d",&n,&m,&k);
    42     for (int i=1; i<=k; ++i)
    43     {
    44         scanf("%d%d%d",&x[i],&y[i],&c[i]);
    45         if (x[i]==1 && y[i]==1) flag[c[i]^1]=0,--k,--i;
    46         else if (x[i]%2==0 && y[i]%2==0) c[i]^=1;
    47     }
    48     if (flag[0]) ans+=Calc();
    49     if (flag[1])
    50     {
    51         for (int i=1; i<=k; ++i)
    52             if (x[i]>1 && y[i]>1) c[i]^=1;
    53         ans+=Calc();
    54     }
    55     if (ans>=MOD) ans-=MOD;
    56     printf("%d
    ",ans); 
    57 }
  • 相关阅读:
    当Django模型迁移时,报No migrations to apply 问题时
    django--各个文件的含义
    django--创建项目
    1013. Battle Over Cities (25)
    1011. World Cup Betting (20)
    1009. Product of Polynomials (25)
    1007. Maximum Subsequence Sum (25)
    1006. Sign In and Sign Out (25)
    1008. Elevator (20)
    1004. Counting Leaves (30)
  • 原文地址:https://www.cnblogs.com/refun/p/9621154.html
Copyright © 2011-2022 走看看