zoukankan      html  css  js  c++  java
  • 【bzoj 2303】【Apio2011】方格染色

    题目:

    http://www.lydsy.com/JudgeOnline/problem.php?id=2303

    题解:

      很神奇的思路,膜一发大佬http://www.cnblogs.com/HHshy/p/5840018.html#undefined

      设S(i,j)=a[i][j]^a[i+1][j]^a[i][j+1]^a[i+1][j+1]。那么将S(1,1)^S(1,2)^...^S(1,j)^S(2,1)^...^S(2,j)^.....^S(i,j)展开,对于i相同的一行(如S(1,1)^S(1,2)^...^S(1,j)),我们可以先然看出其结果为开头的a[i][1]^a[i][j],同时其在下一层的异或结果也是a[i+1][1]^a[i+1][j],那么再把每一行合并,最终我们得到此式的化简:a[1][1]^a[i+1][1]^a[1][j+1]^a[i+1][j+1],然后当i,j均为奇数时,我们得知a[1][1]^a[i+1][1]^a[1][j+1]^a[i+1][j+1]==1,否则为0,再把那个+1缩掉,即:((i|j)&1)==0时,a[1][1]^a[i][1]^a[1][j]^a[i][j]==1,否则为0.设a[1][1]^a[i][1]^a[1][j]^a[i][j]为z,再移一下项,我们得到z^a[1][1]^a[i][j]==a[i][1]^a[1][j],然后枚举a[1][1]的值,再用并查集把有关的a[i][1]与a[1][j]连接起来,判断是否会出现矛盾,如果没有矛盾,我们就得到了一部分答案。最后把两个a[1][1]值的贡献加和即可。

     1 #include<cstdio>
     2 const int N=(int )1e6+5,mod=(int) 1e9;
     3 inline int read(void ){
     4     int s=0;char ch=getchar();
     5     while(ch<'0'||ch>'9')   ch=getchar();
     6     while(ch>='0'&&ch<='9') s=s*10+(ch^48),ch=getchar();
     7     return s;
     8 }
     9 
    10 int n,m,k;
    11 int x[N],y[N],z[N],g[N],f[N];
    12 inline int find(int x){
    13     if(x==f[x]) return x;
    14     int t=find(f[x]);g[x]^=g[f[x]];
    15     return f[x]=t;
    16 }
    17 inline int solve()
    18 {
    19     for(int i=1;i<=n+m;i++)   f[i]=i,g[i]=0; 
    20     f[n+1]=1;
    21     for (int i=1;i<=k;i++)                                  
    22     {                                                                                                                                               
    23         int  u=find(x[i]),v=find(y[i]+n),t=g[x[i]]^g[y[i]+n]^z[i];                                               
    24         if (u!=v) f[u]=v,g[u]=t;                                                                                                                             
    25         else if (t) return 0;                                                                                   
    26     }         
    27     int sum=0;                              
    28     for (int i=1;i<=n+m;i++)
    29         if (f[i]==i)
    30             if (!sum) sum=1;
    31             else {
    32                 sum<<=1;
    33                 sum-=mod*(sum>mod);
    34             }
    35     return sum;
    36 }
    37 int main(){
    38     bool e[2]={1,1};
    39     n=read(),m=read(),k=read();
    40     for(int i=1;i<=k;i++){
    41         x[i]=read(),y[i]=read(),z[i]=read();
    42         if(!((x[i]^1)|(y[i]^1))){
    43             e[z[i]]=0,i--,k--;continue;
    44         }
    45         if(!((x[i]|y[i])&1))    z[i]^=1;
    46     }
    47     int ans=0;
    48     if(e[1])    ans=solve();
    49     if(e[0]){
    50         for(int i=1;i<=k;i++)
    51             if((x[i]^1)&&(y[i]^1)) z[i]^=1;
    52         ans+=solve();
    53         ans-=(ans>mod)*mod;
    54     }
    55     printf("%d
    ",ans);
    56 }

    //承认抄代码。。

  • 相关阅读:
    第二十九课 循环链表的实现
    第二十八课 再论智能指针(下)
    第二十七课 再论智能指针(上)
    第二十六课 典型问题分析(Bugfix)
    普通new和placement new的重载
    leetcode 581. Shortest Unsorted Continuous Subarray
    leetcode 605. Can Place Flowers
    leetcode 219. Contains Duplicate II
    leetcode 283. Move Zeroes
    leetcode 217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/Troywar/p/7327511.html
Copyright © 2011-2022 走看看