题意:
n 个数,给出常数 a、b, 要把这 n 个数分成两个不相交的集合 A、B 。且要满足: 如果某数 x 在 A 里,那么 a-x 也要在 A 里;如果 x 在 B 里,那么 b-x 也要在 B 里。tags:
把 n 个数看成变量,要么在 A,要么在 B,即二判定性,可用 2-SAT 解。对于数 x, 用点 x2 表示它在 A集合,用点 x2+1 表示它在 B 集合。 但重点是如何连边: 1】如果对 x ,有 a-x 存在,那么就加双向边 [ x2, (a-x)2 ] , [ x2+1, (a-x)2+1 ] 。 表示如果 x 在 A集合,那么 a-x 也要在 A集合; 如 x 在 B 集合,那么 a-x 也要在 B集合。 2】如果对 x, 没有 a-x 存在,那么就加单向边 [ x2, x2+1 ] 。 表示如果推出了 x 在 A 集合,我们要否定这种情况,把它转回到 B 集合来。// 469 D#includeusing namespace std;#pragma comment(linker, "/STACK:102400000,102400000")#define rep(i,a,b) for (int i=a; i<=b; ++i)#define per(i,b,a) for (int i=b; i>=a; --i)#define mes(a,b) memset(a,b,sizeof(a))#define INF 0x3f3f3f3f#define MP make_pair#define PB push_back#define fi first#define se secondtypedef long long ll;const int N = 200005;int top, Stack[N<<1];vector< int > G[N<<1];bool mark[N<<1];void Addedge(int u, int uval, int v, int vval) { u = u*2+uval, v = v*2+vval; G[u].PB(v); G[u^1].PB(v^1);}bool dfs(int u, int fa){ if(mark[u^1]) return false; if(mark[u]) return true; mark[u] = true; Stack[top++] = u; for(int to : G[u]) if(!dfs(to, u)) return false; return true;}int n, a, b;ll p[N];map< ll, int > mp;int main(){ scanf("%d%d%d", &n, &a, &b); rep(i,1,n) scanf("%d", &p[i]), mp[p[i]]=i; bool flag; rep(i,1,n) { flag = false; if(mp.find(a-p[i])!=mp.end()) Addedge(i, 0, mp[a-p[i]], 0), flag=true; else G[i*2].PB(i*2+1); if(mp.find(b-p[i])!=mp.end()) Addedge(i, 1, mp[b-p[i]], 1), flag=true; else G[i*2+1].PB(i*2); if(!flag) return printf("NO\n"), 0; } for(int i=2; i<=n*2; i+=2) { if(mark[i]==false && mark[i^1]==false) { top = 0; if(!dfs(i, 0)) { while(top>0) mark[Stack[--top]] = false; if(!dfs(i^1, 0)) return printf("NO\n"), 0; } } } puts("YES"); for(int i=2; i<=n*2; i+=2) if(mark[i]) printf("0 "); else printf("1 "); puts(""); return 0;}