zoukankan      html  css  js  c++  java
  • [CF468B] Two Sets

    [CF468B] Two Sets - 2-sat

    Description

    给定 (n) 个数字,要划分成 (A,B) 两个集合。要求对任意 (x),若 (x)(A) 中则 (a-x) 也在 (A) 中,若 (x)(B) 中则 (b-x) 也在 (B) 中。保证数互不相同。

    Solution

    2-sat,点 (i) 表示第 (a_i)(A) 中,点 (i+n) 表示 (a_i)(B)

    对于每个数 (a_i),如果 (a_j=a-a_i),那么 (i o j)

    对于每个数 (a_i),如果 (a_j=b-a_i),那么 (i+n o j+n)

    记录一下中间一个搞错了的地方,实际上也是经常错的(好像以前干过类似事情但自己忘了)
    2-sat 中,当我们正向考虑选 x 必须选 y 时,实际上也意味着选 y' 必须选 x'
    如果不连这条边会出问题

    #include <bits/stdc++.h>
    using namespace std;
    
    #define reset(a) memset((a), 0, sizeof((a)))
    
    const int N = 4001000;
    struct edge
    {
        int to, next;
    } e[N];
    int flag = 0;
    int head_for[N], tot, head_back[N];
    int n, a, b, x[N], m, cnt, turn[N], belong[N], vis[N];
    void add(int x, int y)
    {
        e[++tot].to = y;
        e[tot].next = head_for[x];
        head_for[x] = tot;
        e[++tot].to = x;
        e[tot].next = head_back[y];
        head_back[y] = tot;
    }
    void dfs1(int u)
    {
        int i;
        vis[u] = 1;
        for (i = head_for[u]; i; i = e[i].next)
            if (!vis[e[i].to])
                dfs1(e[i].to);
        turn[++cnt] = u;
    }
    void dfs2(int u)
    {
        belong[u] = cnt;
        vis[u] = 1;
        for (int i = head_back[u]; i; i = e[i].next)
            if (!vis[e[i].to])
                dfs2(e[i].to);
    }
    void kosaraju()
    {
        for (int i = 1; i <= 2 * n; i++)
            if (!vis[i])
                dfs1(i);
        reset(vis);
        cnt = 0;
        for (int i = 2 * n; i >= 1; i--)
            if (!vis[turn[i]])
                cnt++, dfs2(turn[i]);
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin >> n >> a >> b;
    
        for (int i = 1; i <= n; i++)
        {
            cin >> x[i];
        }
    
        map<int, int> val2id;
        for (int i = 1; i <= n; i++)
        {
            val2id[x[i]] = i;
        }
    
        for (int i = 1; i <= n; i++)
        {
            if (val2id[a - x[i]])
            {
                add(i, val2id[a - x[i]]);
                add(i + n, n + val2id[a - x[i]]);
            }
            else
            {
                add(i, i + n);
            }
            if (val2id[b - x[i]])
            {
                add(i + n, n + val2id[b - x[i]]);
                add(i, val2id[b - x[i]]);
            }
            else
            {
                add(i + n, i);
            }
            flag = 0;
        }
    
        kosaraju();
    
        for (int i = 1; i <= n; i++)
            if (belong[i] == belong[i + n])
            {
                cout << "NO";
                return 0;
            }
        cout << "YES
    ";
        for (int i = 1; i <= n; i++)
        {
            cout << (belong[i] < belong[i + n]) << ' ';
        }
        return 0;
    }
    
  • 相关阅读:
    MySQL索引底层数据结构
    numpy和matplotlib读书笔记
    Python turtle学习笔记 #11933
    turtle笔记
    五角星绘制
    六角形绘制
    叠加等边三角形绘制
    什么叫方法签名
    Java编程思想 第七章
    类加载机制
  • 原文地址:https://www.cnblogs.com/mollnn/p/14615917.html
Copyright © 2011-2022 走看看