Codeforces 469D Two Sets【思维+并查集】
来源:互联网 发布:windows官方商城 编辑:程序博客网 时间:2024/05/17 02:01
Little X has n distinct integers: p1, p2, ..., pn. He wants to divide all of them into two setsA and B. The following two conditions must be satisfied:
- If number x belongs to set A, then number a - x must also belong to setA.
- If number x belongs to set B, then number b - x must also belong to setB.
Help Little X divide the numbers into two sets or determine that it's impossible.
The first line contains three space-separated integers n, a, b (1 ≤ n ≤ 105; 1 ≤ a, b ≤ 109). The next line containsn space-separated distinct integers p1, p2, ..., pn (1 ≤ pi ≤ 109).
If there is a way to divide the numbers into two sets, then print "YES" in the first line. Then printn integers: b1, b2, ..., bn (bi equals either 0, or 1), describing the division. Ifbi equals to0, then pi belongs to setA, otherwise it belongs to set B.
If it's impossible, print "NO" (without the quotes).
4 5 92 3 4 5
YES0 0 1 1
3 3 41 2 4
NO
It's OK if all the numbers are in the same set, and the other one is empty.
题目大意:
给你N个数(distinct),有两个集合A.B,要求如果数字x在集合A中,那么要求a-x也要在集合A中,同理x在B中,要求b-x也要在集合B中。
问能否分出一个可行方案,使得每个数能且只能分配到一个集合中。
思路(思路源自:http://blog.csdn.net/budlele/article/details/39548063):
首先设定两个点作为集合A的root以及集合B的root.
如果有:find(rootA)==find(a【i】),那么我们表示a【i】这个数字分到了集合A中。
同理有:find(rootB)==find(a【i】),那么我们表示a【i】这个数字分到了集合B中。
对于所有a【i】.其总共有几种情况:
①存在数字a-a【i】。那么对应两个数字一定是属于同一集合中的。那么merge(a【i】,a-a【i】);但是因为一个数字可能有多种匹配的数字放到一个集合中的情况,所以a【i】这个数字到底属于哪个集合我们并不是确定的。同理,a-a【i】这个数字到底属于哪个集合我们也不是确定的,但是我们确定a【i】和a-a【i】是可以属于同一集合的。
否则如果不存在,那么这个数字只可能属于集合B.那么merge(a【i】,rootB);此时这种情况我们能够确定一个数字一定属于哪个集合,所以这里一定要进行设定。
②存在数字b-b【i】。那么对应两个数字一定是属于同一集合中的。那么merge(a【i】,b-a【i】);
否则如果不存在,那么这个数字只可能属于集合A.那么merge(a【i】,rootA);
那么对于结果的判定,如果有:find(rootA)==find(rootB)的情况,那么结果就是NO的情况。
否则就是YES的情况,那么我们只要判定find(a【i】)和find(rootA)相等还是和find(rootB)相等即能够判定当前数字到底属于哪个集合了。
Ac代码:
#include<stdio.h>#include<string.h>#include<map>using namespace std;int f[150000];int a[150000];int find(int a){ int r=a; while(f[r]!=r) r=f[r]; int i=a; int j; while(i!=r) { j=f[i]; f[i]=r; i=j; } return r;}void merge(int a,int b){ int A,B; A=find(a); B=find(b); if(A!=B) f[B]=A;}int main(){ int n,A,B; while(~scanf("%d%d%d",&n,&A,&B)) { int cnt=1; map<int ,int >s; for(int i=1;i<=n+2;i++)f[i]=i; for(int i=0;i<n;i++)scanf("%d",&a[i]),s[a[i]]=cnt++; for(int i=0;i<n;i++) { if(s[A-a[i]]>0) { merge(s[a[i]],s[A-a[i]]); } else merge(s[a[i]],n+2); if(s[B-a[i]]>0) { merge(s[a[i]],s[B-a[i]]); } else merge(s[a[i]],n+1); } if(find(n+1)==find(n+2))printf("NO\n"); else { printf("YES\n"); for(int i=0;i<n;i++) { if(find(s[a[i]])==find(n+1))printf("0 "); else printf("1 "); } printf("\n"); } }}
- Codeforces 469D Two Sets【思维+并查集】
- CodeForces Two Sets(并查集)
- Codeforces Round #268 (Div. 2) D Two Sets[并查集]
- codeforces 468B Two Sets 并查集
- codeforces 468B Two Sets 并查集变形
- Codeforces 468B Two Sets 并查集
- CODEFORCES 468B Two Sets ---并查集建树
- Codeforces 469D Two Sets 题解
- Codeforces 469D Two Sets 题解
- Codeforces 699D. Fix a Tree【并查集+思维】
- Codeforces 251D Two Sets
- (one day one problem) codeforces 468/problem/B Two Sets (并查集)
- Codeforces--486D-----Valid Sets思维
- Codeforces 755C 【并查集】【思维】
- codeforces-755【C思维、并查集】
- Codeforces 362D Fools and Foolproof Roads【并查集+优先队列+思维】
- Codeforces 371D Vessels【思维+并查集】经典套路题
- Codeforces Round #218 (Div. 2) D. Vessels(思维 并查集)
- 使用Amazon EC2及OpenVPN搭建属于自己的免费VPN服务器
- ubuntu16.04安装配置mod_python,apxs,apache
- C++ 图基础知识总结
- 自定义Veiw的实践(一)---一个简易侧滑菜单的实现
- hdu 2602 Bone Collector
- Codeforces 469D Two Sets【思维+并查集】
- PAT 1003 乙等 (我要通过) c++
- trunk函数详解
- 求数组中的次大值
- 数位DP-要49-基础DP-hdu3555-四种方法
- MyBatis架构设计及源代码分析(一):MyBatis架构
- 用node.js写的http小爬虫
- 1010: "水仙花数"问题1
- 菜鸟学习Spring——SpringMVC注解版控制层重定向到控制层