• BZOJ 2303 方格染色


    首先考虑四个格子异或值为1。

    然后(重点)发现每个格子的值只和最上面,最左边,和(1,1)的格子的颜色有关。

    枚举(1,1)的颜色,联立方程,可以将未知数减少,那么并查集可做。

    最后算答案的时候,有些连通块颜色确定,有些不确定,不确定的*2即可。

    这题要注意细节!其实一开始的思路最不好想。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 1000500
    #define mod 1000000000
    using namespace std;
    struct pnt
    {
        int x,y,c;
    }p[maxn];
    int n,m,k,fath[maxn<<1],dis[maxn<<1],val[maxn<<1],flag=-1,cnt[maxn<<1];
    void reset()
    {
        for (int i=1;i<=(n-1)+(m-1);i++)
        {
            fath[i]=i;
            dis[i]=0;
            val[i]=-1;
            cnt[i]=0;
        }
    }
    int getfather(int x)
    {
        if (x==fath[x]) return fath[x];
        if (val[x]!=-1)
        {
            if ((val[fath[x]]!=-1) && (val[fath[x]]!=(val[x]^dis[x])))
                return -1;
            val[fath[x]]=val[x]^dis[x];
        }
        int ret=getfather(fath[x]);
        dis[x]^=dis[fath[x]];
        fath[x]=ret;
        return fath[x];
    }
    int f_pow(int a,int b)
    {
        int base=a,ans=1;
        while (b)
        {
            if (b&1) ans=(ans*base)%mod;
            base=(base*base)%mod;
            b>>=1;
        }
        return ans%mod;
    }
    int gets(int r)
    {
        int ans=1;
        if (flag==1-r) return 0;
        reset();
        for (int i=1;i<=k;i++)
        {
            if ((p[i].x==1) && (p[i].y==1))
            {
                if (p[i].c!=r) return 0;
            }
            else if ((p[i].x==1) && (p[i].y!=1)) {if ((val[n+p[i].y-2]!=p[i].c) && (val[n+p[i].y-2]!=-1)) return 0;val[n+p[i].y-2]=p[i].c;}
            else if ((p[i].x!=1) && (p[i].y==1)) {if ((val[p[i].x-1]!=p[i].c) && (val[p[i].x-1]!=-1)) return 0;val[p[i].x-1]=p[i].c;}
            else
            {
                int x=p[i].x-1,y=n+p[i].y-2;
                int f1=getfather(x),f2=getfather(y);
                if ((f1==-1) || (f2==-1)) return 0;
                if (f1==f2)
                {
                    int ret=dis[x]^dis[y]^r;
                    if ((p[i].x%2==0) && (p[i].y%2==0)) ret^=1;
                    if (ret!=p[i].c) return 0;
                }
                else 
                {
                    int ret=p[i].c^dis[x]^dis[y]^r;
                    if ((p[i].x%2==0) && (p[i].y%2==0)) ret^=1;
                    if ((val[f1]!=-1) && (val[f2]!=-1)) 
                    {
                        if ((val[f1]^ret)!=val[f2]) return 0;
                    }
                    else if ((val[f1]==-1) && (val[f2]!=-1)) {fath[f1]=f2;dis[f1]=ret;}
                    else if ((val[f1]!=-1) && (val[f2]==-1)) {fath[f1]=f2;dis[f1]=ret;val[f2]=val[f1]^ret;}
                    else {fath[f1]=f2;dis[f1]=ret;}
                }
            }
        }
        for (int i=1;i<=(n-1)+(m-1);i++)
        {
            int ret=getfather(i);
            if (ret==-1) return 0;
            cnt[ret]++;
        }
        for (int i=1;i<=(n-1)+(m-1);i++)
        {
            if ((fath[i]==i) && (val[i]==-1))
                ans=(ans*2)%mod;
        }
        return ans%mod;
    }
    int main()
    { 
        scanf("%d%d%d",&n,&m,&k);
        for (int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].c);
            if ((p[i].x==1) && (p[i].y==1)) flag=p[i].c;
        }
        printf("%d
    ",(gets(0)+gets(1))%mod);
        return 0;
    }
  • 相关阅读:
    Lambda表达式
    多态的实现原理
    泛型
    tomcat
    nginx
    列举cocoa touch 常用框架
    写出你对MVC模式的理解
    写一个委托的interface
    写一个“标准”宏MIN 这个宏输入两个参数并返回较小的一个
    简介Object-C的内存管理
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5847641.html
Copyright © 2020-2023  润新知