Codeforces 469 D. Two Sets (并查集)

题目链接:Two Sets

题意:

  有n个数,要分成A、B两组,要求如果x∈A则a-x∈A,如果x∈B则b-x∈B,问是否存在一种符合要求的分法。

题解:

  并查集,先增加两个点表示A和B集合的根,对于一个数x,如果a-x存在就把x和a-x放一起,否则就将x和B的根相连,如果b-x存在就把x和b-x放一起,否则就将x和A的根相连,最后看一下A和B集合的根是否相连就可以判断出有没有解了,至于分法就看这个数是和A的根相连还是B的根相连了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAX_N = 1e5 + 9;
 4 int vec[MAX_N],vis[MAX_N];
 5 map<int,int> mp;
 6 int N,M,x;
 7 void init()
 8 {
 9     mp.clear();
10 }
11 int find_f(int x)
12 {
13     if(x == vis[x]) return x;
14     return vis[x] = find_f(vis[x]);
15 }
16 int main()
17 {
18     int a,b;
19     while(cin>>N>>a>>b)
20     {
21         init();
22         for(int i=1;i<=N;i++)
23         {
24             scanf("%d",&vec[i]);
25             mp[vec[i]] = i;
26         }
27         for(int i=0;i<=N+3;i++) vis[i] = i;
28 
29         for(int i=1;i<=N;i++)
30         {
31             if(mp[a-vec[i]] == 0) vis[find_f(mp[vec[i]])] = find_f(N+2);
32             else vis[find_f(i)] = find_f(mp[a-vec[i]]);
33             if(mp[b-vec[i]] == 0) vis[find_f(mp[vec[i]])] = find_f(N+1);
34             else vis[find_f(i)] = find_f(mp[b-vec[i]]);
35         }
36         if(find_f(N+1) == find_f(N+2)) cout<<"NO"<<endl;
37         else
38         {
39             cout<<"YES"<<endl;
40             for(int i=1;i<=N;i++)
41             {
42                 //cout<<"...."<<find_f(i)<<endl;
43                 int x = find_f(N+1);
44                 int y = find_f(N+2);
45                 if(find_f(i) == x) printf("0 ");
46                 else printf("1 ");
47             }
48             cout<<endl;
49         }
50     }
51     return 0;
52 }
53 /*
54 70 416035 416023
55 70034 70322 345689 345965 345701 70046 345737 345713 70166 345821 70010 345749 345677 345725 69962 345869 70178 70310 345785 69998 70070 69974 70058 346001 70106 345953 70226 70154 345929 69950 70298 346049 70346 345989 70286 69986 345893 70082 70238 345797 70250 345833 70334 345845 70094 70118 70202 345977 70262 70274 70190 345941 346025 345761 345773 70142 70022 70130 345881 345917 70358 345905 345665 346013 346061 345809 345857 346037 346073 70214
56 
57 
58 */

转载自:http://blog.csdn.net/m0_37729344/article/details/73605481

转载于:https://www.cnblogs.com/doggod/p/8516344.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值