CodeForces Two Sets(并查集)

来源:互联网 发布:刘慈欣光荣与梦想知乎 编辑:程序博客网 时间:2024/05/19 21:45

题目链接:http://codeforces.com/problemset/problem/468/B

题目大意:给你N个互不相同的整数,再给两个整数a,b,问能否把这N个数分成两部分,使得在a这个集合中的任一个数ai,都存在a-ai也在a 这个集合中,对b集合也同理。如果不存在一种合理分法,输出No,否则输出YES,并输出任一种合理分组。

解题思路:

首先我们先假设存在一种合理的方案,则有  对于任一个数x,肯定在a,b集合中的一个。同时如果方案合理,最后的结果a,b集合中的元素没有交集。

1.对于一个数x,如果a-x不存在,则x肯定在b分组中(假定分组成立),则把x和b分组并起来;如果同时b-x也不存在的话,则再把x和a分组并起来,此时a和b分组被并了起来,显然这种方案不合理。

2.对于一个数x,如果a-x存在,则把x和a-x对应的下标并起来,此时并不能说明x属于集合a,因为可能存在N=2,a=8,b=20,4,16,这样的数据,只有当b-x不存在时,才把x和a的下标并起来。

3,如果b-x也存在时,就把x和b-x也的下标也并起来,此时如果x!=a-x!=b-x时,说明a和b集合公用x,即这种方案a和b被并起来,这种方案也不合理。此时如果x==a-x!=b-x,显然应分组为b,当然特例就是a和b相等,此时任何分组都可以。

总的情况应该这几种。

对于代码,有以下几点感觉很好:

1,map映射,使得查找成对的数字查找更方便。

2,虚拟出两个a,b集合的根结点n+1和n+2;

3,并查集的特殊处理;


关于这道题我自己写的是满足a集合就放在a集合中, 满足b集合在放在b集合中;然后用各种标记和判断来判是否合法, 但是就写不过去, 然而看了别人的题解后发现,如果反着考虑会省很多麻烦, 所以写博客来提醒一下。

#include<stdio.h>#include<string.h>#include<algorithm>#include<map>using namespace std;const int maxn = 1e5 + 100;int f[maxn], s[maxn];int find_set(int x){    return x==f[x]? x : f[x]=find_set(f[x]);}void merge_set(int x, int y){    int fx = find_set(x);    int fy = find_set(y);    if(fx != fy)        f[fx] = fy;}int main(){    int n, a, b, x;    scanf("%d%d%d", &n, &a, &b);    map<int, int> M;    for(int i = 1; i <= n+2; i++)        f[i] = i;    for(int i = 1; i <= n; i++)    {        scanf("%d", &s[i]);        M[s[i]] = i;    }    for(int i = 1; i <= n; i++)    {        x = a - s[i];        if(M[x] != 0)            merge_set(i, M[x]);        else            merge_set(i, n+2);        x = b - s[i];        if(M[x] != 0)            merge_set(i, M[x]);        else            merge_set(i, n+1);    }    int fx = find_set(n+1);    int fy = find_set(n+2);    if(fx == fy)        puts("NO");    else    {        puts("YES");        for(int i = 1; i <= n; i++)        {            int x = find_set(i);            if(i == 1)            {                if(x == fx)                    printf("0");                else                    printf("1");            }            else            {                if(x == fx)                    printf(" 0");                else                    printf(" 1");            }        }    }    return 0;}


0 0
原创粉丝点击