zoukankan      html  css  js  c++  java
  • bzoj2303

    并查集+数学

    这道题网上好像有两种解法。

    这位写的很可读:http://blog.csdn.net/unicornt_/article/details/51901225

    然后看完大概就懂了做法,但是实现上还有很多细小的地方。

    cnt要-1,因为第一行和第一列会算两次。

    数组要开四倍。

    至于为什么要拆成两个点,这是因为分开考虑01.

    为什么两个flag都要赋值?因为有可能根是放在列上了,就判不到了。

    还需要思考一下。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1001000;
    const ll mod = 1000000000;
    struct dsu {
        int fa[N * 4];
        void ini(int n)
        {
            for(int i = 1; i <= n; ++i)
                fa[i] = i;
        }
        int find(int x)
        {
            return x == fa[x] ? x : fa[x] = find(fa[x]);
        }
        void connect(int x, int y)
        {
            fa[find(x)] = find(y);
        }
        bool same(int x, int y)
        {
            return find(x) == find(y);
        }
    } u;
    int n, m, k, s = -1;
    int x[N], y[N], c[N];
    ll ans;
    bool flag[N * 4];
    ll power(ll x, ll t)
    {
        ll ret = 1;
        for(; t; t >>= 1, x = x * x % mod) if(t & 1) ret = ret * x % mod;
        return ret;
    }
    void solve(int s)
    {
        u.ini(2 * n + 2 * m + 100);
        u.connect(2, 2 + 2 * n);
        u.connect(3, 2 + 2 * n + 1);
        for(int i = 1; i <= k; ++i)
        {
            int p = 0;
            if(x[i] % 2 == 0 && y[i] % 2 == 0) p = 1;
            p = p ^ c[i] ^ s;
            if(p)
            {
                u.connect(x[i] * 2, y[i] * 2 + 1 + 2 * n);
                u.connect(x[i] * 2 + 1, y[i] * 2 + 2 * n);
            }
            else
            {
                u.connect(x[i] * 2, y[i] * 2 + 2 * n);
                u.connect(x[i] * 2 + 1, y[i] * 2 + 2 * n + 1);
            }
        }
        int cnt = 0;
        memset(flag, 0, sizeof(flag));
        for(int i = 1; i <= n; ++i)
        {
            if(u.same(i * 2, i * 2 + 1))
                return;
            if(!flag[u.find(i * 2)])
            {
                flag[u.find(i * 2)] = flag[u.find(i * 2 + 1)] = 1;
                ++cnt;
            }
        }
        for(int i = 1; i <= m; ++i)
        {
            if(u.same(i * 2 + 2 * n, i * 2 + 2 * n + 1))
                return;
            if(!flag[u.find(i * 2 + 2 * n)])
            {
                flag[u.find(i * 2 + 2 * n)] = flag[u.find(i * 2 + 2 * n + 1)] = 1;
                ++cnt;
            }
        }
        ans = (ans + power(2ll, cnt - 1)) % mod;
    }
    int main()
    {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= k; ++i)
        {
            scanf("%d%d%d", &x[i], &y[i], &c[i]);
            if(x[i] == 1 && y[i] == 1) s = c[i];
        }
        if(s != 1) solve(0);
        if(s != 0) solve(1);
        printf("%lld
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    前端开发面试题总结之——HTML
    HashMap的那些事
    抽象同步队列AQS(中)—— AQS的重点方法解析
    抽象同步队列AQS(上)—— 宏观上理解AQS
    synchronized原理详解
    volatile原理详解
    JMM模型详解
    计算机运行时内存&处理器CPU初步认知
    mysql-索引详解
    mysql-事务隔离机制&mvcc原理
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7091382.html
Copyright © 2011-2022 走看看