码迷,mamicode.com
首页 > 其他好文 > 详细

[CF468B] Two Sets - 2-sat

时间:2021-04-06 14:31:06      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:sar   val   return   main   flag   span   ret   add   ==   

[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 \to j\)

对于每个数 \(a_i\),如果 \(a_j=b-a_i\),那么 \(i+n \to 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\n";
    for (int i = 1; i <= n; i++)
    {
        cout << (belong[i] < belong[i + n]) << ‘ ‘;
    }
    return 0;
}

[CF468B] Two Sets - 2-sat

标签:sar   val   return   main   flag   span   ret   add   ==   

原文地址:https://www.cnblogs.com/mollnn/p/14615917.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!