Как мне решить эту проблему, используя алгоритм поиска объединения?

Вопрос: http://codeforces.com/contest/468/problem/B

Маленький X имеет n различных целых чисел: p1, p2, …, pn. Он хочет разделить их все на два набора A и B. Следующие два условия должны быть выполнены:

Если число x принадлежит множеству A, то число a — x также должно принадлежать множеству A.
Если число x принадлежит множеству B, то число b — x также должно принадлежать множеству B.
Помогите Маленькому Х разделить числа на два набора или определить, что это невозможно.

вход
Первая строка содержит три разделенных пробелом целых числа 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.

Если это невозможно, выведите «NO» (без кавычек).

Теперь я разработал следующий код:

#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;
}

По сути, попробуйте объединить каждый элемент либо в наборе A, либо в наборе B. И, наконец, выведите NO, если оба они объединены по очереди. Тем не менее, это дает неправильный ответ на входе, как:

3 3 4
1 2 4

Выход должен быть: NO тогда как мой код дает вывод как

YES
0 0 1

Где я ошибаюсь в моей логике? Пожалуйста помоги!

1

Решение

Рассмотрим следующие случаи для 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]

Что бы ни случилось, если вы столкнетесь с ситуацией 3. или 4. вы хотите сообщить об ошибке («НЕТ»).

Если все числа p[i] относятся к случаю 1. или 2. результат должен быть действительным.

Вы должны проверять свой код построчно, если он совместим с приведенными здесь случаями.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]