BZOJ 2303 [Apio2011]方格染色

易或方程+带权并查集

我好SB啊,挂题解吧。。。。。。
http://www.cnblogs.com/HHshy/p/5840018.html

#include<cstdio>
#include<cstring>
#define N 2333333
#define MOD 1000000000
#define R register
using namespace std;
namespace runzhe2000
{
    int read()
    {
        R int r = 0; R char c = getchar();
        for(; c < '0' || c > '9'; c = getchar());
        for(; c >='0' && c <='9'; r = r*10+c-'0', c = getchar());
        return r;
    }
    int n, m, k, f[N], fv[N], vis[N], X[N], Y[N], V[N];
    int find(R int x)
    {
        if(f[x] == x) return x;
        else
        {
            R int y = find(f[x]);
            fv[x] ^= fv[f[x]];
            return f[x] = y;
        }
    }
    int solve()
    {
        R int x, y, v, fx, fy;
        for(R int i = 1; i <= n+m; i++) f[i] = i; memset(fv, 0, sizeof(fv));
        for(R int i = 1; i <= k; i++)
        {
            x = X[i]; y = Y[i] + n; v = V[i];
            if(x == 1 || y == n+1) continue;
            fx = find(x);
            fy = find(y);
            R int w = v ^ vis[1] ^ (x%2==0&&y%2==0?1:0);
            if(fx != fy)
            {
                f[fx] = fy;
                fv[fx] = w^fv[x]^fv[y];
            }
            else if((fv[x]^fv[y]) != w) return 0;
        }
        for(R int i = 1; i <= k; i++)
        {
            x = X[i]; y = Y[i] + n; v = V[i];
            if(x == 1 || y == n+1)
            {
                if(y == n+1) y = 1;
                x == 1 ? x = y : 0;
                R int fx = find(x);
                if(vis[fx] != -1)
                {
                    if((v ^ vis[fx]) != fv[x]) return 0;
                }
                else vis[fx] = v ^ fv[x];
            }
        }
        R int ans = 1;
        for(R int i = n+m; i >= 1; i--)
        {
            R int fi = find(i);
            if(i == fi && vis[i] == -1 && i != n+1) (ans <<= 1) %= MOD;
        }
        return ans;
    }
    void main()
    {
        n = read(), m = read(), k = read();
        for(int i = 1; i <= k; i++) X[i] =read(), Y[i] = read(), V[i] = read();
        int ans = 0;
        memset(vis, -1, sizeof(vis)); vis[1] = 0; (ans += solve()) %= MOD;
        memset(vis, -1, sizeof(vis)); vis[1] = 1; (ans += solve()) %= MOD;
        printf("%d\n",ans);
    }
}
int main()
{
    runzhe2000::main();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值