Language: C++

#include <iostream>
#include <string>
#include <vector>
#include <set>
#define N 601

using namespace std;

int roots[N];

enum Assignment { UNASSIGNED, DIVINE, DEVILISH, CONFLICT };

struct node {
  int index;
  int n_people;
  vector<int> negatives;
  int assignment; 
};

struct negative { //negative links
  int x;
  int y;
};
  

int root(int x) { // return root of element
  if (x == roots[x]) {
    return x;
  } else {
    return root(roots[x]);
  }
}

void clean_up_roots() { // attach all to root
  for (int i = 0; i < N; i++) {
    if (roots[i] != root(i)) {
	roots[i] = root(i);
      }
  }
}
  
bool same(int x, int y) { // return true if same root
  return (root(x) == root(y));
}

void unite(int x, int y) { // union 
  roots[root(x)] = root(y);
}

int solutions = 0; //number of solutions, > 1  means ambiguous
vector<int> solved_vec; //vector containing group index of DIVINE 


void goal_test(vector<node> *nodes_ref, int p1, int p2) { // test if goal state found
  int divine_count = 0;
  int devilish_count = 0;
  for (vector<node>::iterator it = nodes_ref->begin(); it!= nodes_ref->end(); it++) {
    if (it->assignment == DIVINE) {
      divine_count += it->n_people;
    } else if (it->assignment == DEVILISH ) {
      devilish_count += it->n_people;
    } else {
      return;
    }
  }
  //cout << "goal test, divine_count and devilish_count: " << divine_count << " " << devilish_count << endl;
  
  if (divine_count == p1 && devilish_count == p2) { 
    solutions++;
    if (solutions == 1) { // if first solution, store groups in solution vector
      for (vector<node>::iterator sol = nodes_ref->begin(); sol!= nodes_ref->end(); sol++) {
	if (sol->assignment == DIVINE) solved_vec.push_back(sol->index);
      }
    }
  } else if (divine_count == p2 && devilish_count == p1) { //symmetrical
    solutions++;
    if (solutions == 1) {
      for (vector<node>::iterator sol = nodes_ref->begin(); sol!= nodes_ref->end(); sol++) {
	if (sol->assignment == DEVILISH) solved_vec.push_back(sol->index);
      }
    }
  }
}

void propagate(vector<node> *nodes_copy, int index, bool assignment) {
  //propagate assignments based on negative links
  vector<node>::iterator cur = nodes_copy->begin();
  while (cur->index != index) cur++;
  if (cur->assignment == CONFLICT) { //failed
    return;
  }
  if (assignment) { //DIVINE assignment
    if (cur->assignment == DEVILISH) { //conflicting assignment
      cur->assignment = CONFLICT; //prevent goal test from succeeding
      return;
    }
    if (cur->assignment == DIVINE) return; //already assigned
    cur->assignment = DIVINE; //assign and propagate
    for (vector<int>::iterator neg = cur->negatives.begin(); neg != cur->negatives.end(); neg++) {
      propagate(nodes_copy, *neg, false);
    }
  } else { //DEVILISH assignment
    if (cur->assignment == DIVINE) { //conflicting assignment
      cur->assignment = CONFLICT;
      return;
    }
    if (cur->assignment == DEVILISH) return; //already assigned
    cur->assignment = DEVILISH; //assign and propagate
    for (vector<int>::iterator neg = cur->negatives.begin(); neg != cur->negatives.end(); neg++) {
      propagate(nodes_copy, *neg, true);
    }
  }
}



void assign(vector<node> nodes_copy, int p1, int p2, int index, bool assignment) {
  //assignment in new stack, true for DEVINE, false for DEVILISH
  if (solutions > 1) return; //prune - too many solutions
  vector<node>::iterator cur = nodes_copy.begin();
  while (cur->index != index) cur++;
  if (assignment) { //DIVINE assignment
    cur->assignment = DIVINE; //assign and propagate
    for (vector<int>::iterator neg = cur->negatives.begin(); neg != cur->negatives.end(); neg++) {
      propagate(&nodes_copy, *neg, false);
    }
  } else { //DEVILISH assignment
    cur->assignment = DEVILISH; //assign and propagate
    for (vector<int>::iterator neg = cur->negatives.begin(); neg != cur->negatives.end(); neg++) {
      propagate(&nodes_copy, *neg, true);
    }
  } 
  while (cur != nodes_copy.end() && cur->assignment != UNASSIGNED) {
    if (cur->assignment == CONFLICT) return; //failed
    cur++; //increment until unassigned group found
  }
  if (cur == nodes_copy.end()) { 
    goal_test(&nodes_copy, p1, p2); //all assigned, do goal test
  } else {
    //try both divine and devilish assignments
    assign(nodes_copy, p1, p2, cur->index, true);
    assign(nodes_copy, p1, p2, cur->index, false);
  }
}


int main() {

  while (true) {
    int n, p1, p2;
    cin >> n >> p1 >> p2; 
    if (n == 0 && p1 == 0 && p2 == 0) break;
    
    //clear solutions
    solutions = 0;
    solved_vec.clear();
    
    //initialize roots
    for (int i = 0; i < N; i++) {
      roots[i] = i;
    }

    vector<negative> negative_links;
    
    for (int i = 0; i < n; i++) {
      int x, y;
      string a;
      cin >> x >> y >> a;
      if (a == "yes") {
	unite(x, y);
      } else if (a == "no") {
	negative negative_link = {x, y};
	negative_links.push_back(negative_link);
      }
    }

    if (p1 == p2) {
      cout << "no" << endl;
      continue;
    }

    clean_up_roots();

    /*for (int i = 1; i <= p1+p2; i++) {
      cout << "root of : " << i << " is: " << roots[i] << endl;
    }
    cout << "end" << endl;*/

    node nodes[N];

    //initialize nodes
    for (int i = 0; i < N; i++) {
      nodes[i].index = i;
      nodes[i].n_people = 0;
      nodes[i].assignment = UNASSIGNED; //unassigned
    }

    for (int i = 1; i <= p1+p2; i++) {
      nodes[roots[i]].n_people++;
    }

    for (vector<negative>::iterator it = negative_links.begin(); it != negative_links.end(); ++it) {
      nodes[roots[it->x]].negatives.push_back(roots[it->y]);
      nodes[roots[it->y]].negatives.push_back(roots[it->x]);
    }

    //printing function for nodes
    /*
    for (int i = 1; i <= p1+p2; i++) {
      if (nodes[i].n_people > 0) {
	cout << i << " " <<  nodes[i].n_people << endl;
	cout << "negatives:" << endl;
	for (vector<int>::iterator it = nodes[i].negatives.begin(); it  != nodes[i].negatives.end(); ++it) {
	  cout << *it << endl;
	}
      }
    }
    */

    //backtrack vector
    vector<node> backtrack_vec;
    for (int i = 1; i <= p1+p2; i++) {
      if (nodes[i].n_people > 0) {
	node new_node = nodes[i];
	backtrack_vec.push_back(new_node);
      }
    }

  
    int index = backtrack_vec.front().index;

    assign(backtrack_vec,  p1, p2, index,  true);
    if (solutions == 1) {
      for (int i = 0; i < N; i++) {
	if (find(solved_vec.begin(), solved_vec.end(), roots[i]) != solved_vec.end()) {
	  cout << i << endl;
	}
	cout << "end" << endl;
      }
    } else {
      cout << "no" << endl;
    }
    
    
  }
}

Compiler output:
a.cc: In function 'int main()':
a.cc:235:17: error: no matching function for call to 'find(std::vector<int>::iterator, std::vector<int>::iterator, int&)'
  235 |         if (find(solved_vec.begin(), solved_vec.end(), roots[i]) != solved_vec.end()) {
      |             ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/14/bits/locale_facets.h:48,
                 from /usr/include/c++/14/bits/basic_ios.h:37,
                 from /usr/include/c++/14/ios:46,
                 from /usr/include/c++/14/ostream:40,
                 from /usr/include/c++/14/iostream:41,
                 from a.cc:1:
/usr/include/c++/14/bits/streambuf_iterator.h:435:5: note: candidate: 'template<class _CharT2> typename __gnu_cxx::__enable_if<std::__is_char<_CharT2>::__value, std::istreambuf_iterator<_CharT> >::__type std::find(istreambuf_iterator<_CharT>, istreambuf_iterator<_CharT>, const _CharT2&)'
  435 |     find(istreambuf_iterator<_CharT> __first,
      |     ^~~~
/usr/include/c++/14/bits/streambuf_iterator.h:435:5: note:   template argument deduction/substitution failed:
a.cc:235:17: note:   '__gnu_cxx::__normal_iterator<int*, std::vector<int> >' is not derived from 'std::istreambuf_iterator<_CharT>'
  235 |         if (find(solved_vec.begin(), solved_vec.end(), roots[i]) != solved_vec.end()) {
      |             ~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~