标签:sar val return main flag span ret add ==
给定 \(n\) 个数字,要划分成 \(A,B\) 两个集合。要求对任意 \(x\),若 \(x\) 在 \(A\) 中则 \(a-x\) 也在 \(A\) 中,若 \(x\) 在 \(B\) 中则 \(b-x\) 也在 \(B\) 中。保证数互不相同。
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;
}
标签:sar val return main flag span ret add ==
原文地址:https://www.cnblogs.com/mollnn/p/14615917.html