• BZOJ2303 APIO2011方格染色(并查集)


      比较难想到的是将题目中的要求看做异或。那么有ai,j^ai+1,j^ai,j+1^ai+1,j+1=1。瞎化一化可以大胆猜想得到a1,1^a1,j^ai,1^ai,j=(i-1)*(j-1)&1。也就是说,确定第一行和第一列的颜色,就可以确定整个矩阵。现在如果没有已填的格子的限制,答案就是2n+m-1

      然后考虑已填格子。假设固定了a1,1,那么其影响到的就是a1,j和ai,1。即要求两者相同或不同。于是可以把每个格子的染色情况拆成两个点,根据已填格子将其连边,同一连通块内的点只要选择一个就必须全部选择。那么方案数就是2连通块个数/2。注意特判第一行或第一列格子已填的情况。

      细节比较麻烦,写完也不知道自己在干啥。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define P 1000000000
    #define N 100010
    int n,m,k,fa[N<<2],color[N<<2];
    struct data{int x,y,c;
    }a[N];
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    int solve(int c)
    {
        memset(color,0,sizeof(color));
        for (int i=1;i<=(n+m-2<<1);i++) fa[i]=i;
        for (int i=1;i<=k;i++)
        if (a[i].x!=1&&a[i].y!=1)
        if ((a[i].c==c)^(((a[i].x-1)&1)*(a[i].y-1)&1)) fa[find((a[i].x-1<<1)-1)]=find((n+a[i].y-2<<1)-1),fa[find(a[i].x-1<<1)]=find(n+a[i].y-2<<1);
        else fa[find((a[i].x-1<<1)-1)]=find(n+a[i].y-2<<1),fa[find(a[i].x-1<<1)]=find((n+a[i].y-2<<1)-1);
        int cnt=0;
        for (int i=1;i<=n+m-2;i++) if (find((i<<1)-1)==find(i<<1)) return 0;
        for (int i=1;i<=k;i++)
        {
            if (a[i].x==1&&a[i].y==1){if (a[i].c!=c) return 0;}
            else
            {
                if (a[i].y==1)
                {
                    if (color[find((a[i].x-1<<1)-a[i].c)]!=-1) color[find((a[i].x-1<<1)-a[i].c)]=1;else return 0;
                    if (color[find((a[i].x-1<<1)-(a[i].c^1))]!=1) color[find((a[i].x-1<<1)-(a[i].c^1))]=-1;else return 0;
                }
                if (a[i].x==1)
                {
                    if (color[find((n+a[i].y-2<<1)-a[i].c)]!=-1) color[find((n+a[i].y-2<<1)-a[i].c)]=1;else return 0;
                    if (color[find((n+a[i].y-2<<1)-(a[i].c^1))]!=1) color[find((n+a[i].y-2<<1)-(a[i].c^1))]=-1;else return 0;
                }
            }
        }
        for (int i=1;i<=(n+m-2<<1);i++)
        if (find(i)==i&&!color[i]) cnt++;
        cnt>>=1;
        int ans=1;while (cnt--) ans=(ans<<1)%P;
        return ans;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2303.in","r",stdin);
        freopen("bzoj2303.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),k=read();
        for (int i=1;i<=k;i++) a[i].x=read(),a[i].y=read(),a[i].c=read();
        cout<<(solve(0)+solve(1))%P;
        return 0;
    }
  • 相关阅读:
    织梦删除不需要的文件及文件安全设置
    织梦安全设置
    阿里云一个虚拟主机安装多个织梦系统
    显示织梦模板不存在的解决方法
    织梦安装
    织梦修改数据库密码
    CSS实现兼容性的渐变背景(gradient)效果
    css边框样式、边框配色、边框阴影、边框圆角、图片边框
    织梦后台编辑器添加中文字体
    织梦安装百度编辑器
  • 原文地址:https://www.cnblogs.com/Gloid/p/9560839.html
Copyright © 2020-2023  润新知