小X有n个互不相同的整数: p1,p2,...,pn 。他想把这些整数分到两个集合A和B里边。但是要符合下面两个条件。
· 如果x属于A,那么a-x也肯定属于A。
· 如果x属于B,那么b-x也肯定属于B。
判断一下是否存在一种方案来分配这些数字到集合A,B中。
注意:如果一个集合为空也是可以的。
Input
单组测试数据。 第一行有三个整数n,a,b (1≤n≤10^5; 1≤a,b≤10^9)。 第二行有n个不一样的整数 p1,p2,...,pn (1≤pi≤10^9).
Output
如果可行,那么输出YES,否则输出NO。
Input示例
样例输入1 4 5 9 2 3 4 5
Output示例
样例输出1 YES
此题的思路与 hiho一下 第一百三十四周 #1468 : 2-SAT·hihoCoder新春晚会 【2-SAT 之 枚举--搜索】 类似
都是从头开始枚举这个点的两个情况---然后收到这个枚举影响的点加入队列继续枚举----看情况是否成立。
可以先预处理出来每个数的A连点和B连点。
当考虑 i 为A时 ,判断 i 和 i的A连点是否可以为A --可以的话将 i和i的A连点 放入队列并标记---
当从队列中取时 , 判断 i 是否有 B连点, 当有B连点j的话,因为 i 已进入A ,那么 j 就不能进入B --- 即只能进入A -------- (如果有矛盾的情况,则枚举失败,所有此次枚举标记的点恢复未标记状态。)
考虑 i 为 B 的方法与上面一致-.- ------------- 飘过-.-
代码:
#include<stdio.h> #include<string.h> #include<queue> #include<stack> #include<iostream> #include<algorithm> using namespace std; int n,a[100100],b[100100][2],ans[100100]; queue<int > qa; stack<int > sa; void my_clear() { while (!qa.empty()) qa.pop(); } void myjinA(int x) { qa.push(x); sa.push(x); } int main() { int t,A,B,k,x,y; cin>>n>>A>>B; for (int i=0;i<n;i++) cin>>a[i]; sort(a,a+n); memset(b,-1,sizeof(b)); memset(ans,-1,sizeof(ans)); bool fafe=true; for (int i=0;i<n;i++) { k=lower_bound(a,a+n,A-a[i])-a; if (k>=0&&k<n&&a[k]==A-a[i]) b[i][0]=k; k=lower_bound(a,a+n,B-a[i])-a; if (k>=0&&k<n&&a[k]==B-a[i]) b[i][1]=k; if (b[i][0]==b[i][1]&&b[i][0]==-1) fafe=false; } if (!fafe) { printf("NO\n"); return 0; } for (int i=0;i<n;i++) { if (ans[i]==-1) { //---------入A if (b[i][0]!=-1&&ans[i]==-1&&ans[b[i][0]]==-1) { my_clear(); x=i;y=b[x][0]; myjinA(x); myjinA(y); ans[x]=0; ans[y]=0; while (!qa.empty()) { x=qa.front(); qa.pop(); if (b[x][1]!=-1&&ans[b[x][1]]==-1) { x=b[x][1]; if (b[x][0]!=-1&&ans[b[x][0]]==-1) { y=b[x][0]; myjinA(x); myjinA(y); ans[x]=0; ans[y]=0; } else { fafe=false; } } if (!fafe) break; } if (!fafe) { while (!sa.empty()) { x=sa.top(); sa.pop(); ans[x]=-1; } } } //入B if (b[i][1]!=-1&&ans[i]==-1&&ans[b[i][1]]==-1) { fafe=true; my_clear(); x=i;y=b[x][1]; myjinA(x); myjinA(y); ans[x]=1; ans[y]=1; while (!qa.empty()) { x=qa.front(); qa.pop(); if (b[x][0]!=-1&&ans[b[x][0]]==-1) { x=b[x][0]; if (b[x][1]!=-1&&ans[b[x][1]]==-1) { y=b[x][1]; myjinA(x); myjinA(y); ans[x]=1; ans[y]=1; } else { fafe=false; } } if (!fafe) break; } if (!fafe) { while (!sa.empty()) { x=sa.top(); sa.pop(); ans[x]=-1; } } } if (!fafe) break; } if (ans[i]==-1) { fafe=false;break; } } if (fafe) printf("YES\n"); else printf("NO\n"); return 0; } /* 3 11 12 4 7 8 3 5 6 2 3 4 */