如何使用union-find算法解决这个问题?

时间:2015-11-15 07:16:26

标签: c++ arrays algorithm union-find

问题:http://codeforces.com/contest/468/problem/B

小X有n个不同的整数:p1,p2,...,pn。他想将所有这些分成两组A和B.必须满足以下两个条件:

如果数字x属于集合A,则数字a-x也必须属于集合A. 如果数字x属于集合B,则数字b-x也必须属于集合B. 帮助小X将数字分成两组或确定它是不可能的。

输入 第一行包含三个空格分隔的整数n,a,b(1≤n≤105;1≤a,b≤109)。下一行包含n个以空格分隔的不同整数p1,p2,...,pn(1≤pi≤109)。

输出 如果有办法将数字分成两组,则在第一行中打印“YES”。然后打印n个整数:b1,b2,...,bn(bi等于0或1),描述除法。如果bi等于0,则pi属于集合A,否则它属于集合B.

如果不可能,请打印“否”(不带引号)。

现在,我开发了以下代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>

using namespace std;

int n,a,b,id;
int p[100100];
set<int> st;
map<int,int> mp;

int fa[100100];

int find(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}

void Bing(int a,int b)
{
    int A=find(a),B=find(b);
    if(A==B) return ;
    fa[B]=A;
}

int main()
{
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",p+i);
        st.insert(p[i]);
        mp[p[i]]=++id;
        fa[i]=i;
    }
    fa[n+1]=n+1;///A
    fa[n+2]=n+2;///B

    for(int i=1;i<=n;i++)
    {
        int x=p[i];
        int flag = 0;
        if(st.count(a-x))
        {
            Bing(mp[x],mp[a-x]);
            flag = 1;
        }
        else
        {
            Bing(n+1,mp[x]);
            flag = 1;
        }
        if(st.count(b-x) && flag == 0)
        {
            Bing(mp[x],mp[b-x]);
        }
        else if (flag == 0)
        {
            Bing(n+2,mp[x]);
        }
    }

    if(find(n+1)==find(n+2))
    {
        puts("NO");
    }
    else
    {
        puts("YES");
        for(int i=1;i<=n;i++)
        {
            printf("%d ",find(i)==find(n+1));
        }
        putchar(10);
    }

    return 0;
}

基本上,尝试将每个元素与Set A或Set B合并。然后如果两个元素依次合并,则最后输出NO。但是,这给出了输入的错误答案:

3 3 4
1 2 4

输出应该是:NO而我的代码输出为

YES
0 0 1 

我的逻辑在哪里出错了?请帮忙!

1 个答案:

答案 0 :(得分:0)

请考虑以下情况,P是所有输入数字p[i]的集合:

  1. 有一个n1 in P符合n1 = a - p[i],但没有符合n2 in P的数字n2 = b - p[i]
  2. 有一个n1 in P符合n1 = b - p[i],但没有符合n2 in P的数字n2 = a - p[i]
  3. 没有数字n in P满足n = a - p[i]n = b - p[i]
  4. 有一个n1 in P符合n1 = a - p[i]n2 in P符合n2 = b - p[i]
  5. 的数字p[i]

    如果您遇到其他情况,如果遇到情况3.或4.您想报告失败(“否”)。

    如果所有数字if let emails = users.allDocuments[0].objectForKey("emails") where emails.count > 0 { if let address = emails[0]["address"] as? String { print(address) } } 属于案例1或2.结果应该有效。

    如果代码与此处提供的案例兼容,则应逐行检查代码。