#include #include #include #include #include #include #include #include #include #include #include #include #include struct Creature { int p1; int p2; char color; }; bool tryCase(const std::vector &creatures, uint64_t mask, std::string &sol) { int n = creatures.size(); struct AlleleData { AlleleData() : childInequality('a'), indegree(0), outdegree(0) { } std::set childEqualities; char childInequality; char alleles[2]; int indegree; std::vector children; int outdegree; }; std::vector data(n); for (int i = 0; i < n; i++) { if (creatures[i].p1 != -1) { data[creatures[i].p1].indegree++; data[creatures[i].p1].children.push_back(i); data[i].outdegree++; } if (creatures[i].p2 != -1) { data[creatures[i].p2].indegree++; data[creatures[i].p2].children.push_back(i); data[i].outdegree++; } } std::deque toprocess; for (int i = 0; i < n; i++) if (data[i].indegree == 0) toprocess.push_back(i); while (!toprocess.empty()) { int cur = toprocess.front(); toprocess.pop_front(); int p1 = creatures[cur].p1; int p2 = creatures[cur].p2; if (mask & (1ULL << cur)) std::swap(p1, p2); if (data[cur].childEqualities.size() > 2) { return false; } else if (data[cur].childEqualities.size() == 2) { auto it = data[cur].childEqualities.begin(); char al1 = *it; it++; char al2 = *it; if (al1 != creatures[cur].color) return false; if (al2 < data[cur].childInequality) return false; data[cur].alleles[0] = al1; data[cur].alleles[1] = al2; if(p1 != -1) data[p1].childEqualities.insert(al1); if(p2 != -1) data[p2].childEqualities.insert(al2); } else if (data[cur].childEqualities.size() == 1) { auto it = data[cur].childEqualities.begin(); char al2 = *it; char al1 = creatures[cur].color; if (al1 != al2) { if (al2 < al1) return false; if (al2 < data[cur].childInequality) return false; data[cur].alleles[0] = al1; data[cur].alleles[1] = al2; if(p1 != -1) data[p1].childEqualities.insert(al1); if(p2 != -1) data[p2].childEqualities.insert(al2); } else { al2 = std::max(al2, data[cur].childInequality); data[cur].alleles[0] = al1; data[cur].alleles[1] = -al2; if(p1 != -1) data[p1].childEqualities.insert(al1); if(p2 != -1) data[p2].childInequality = std::max(data[p2].childInequality, al2); } } else { char al1 = creatures[cur].color; char al2 = std::max(al1, data[cur].childInequality); data[cur].alleles[0] = al1; data[cur].alleles[1] = -al2; if(p1 != -1) data[p1].childEqualities.insert(al1); if(p2 != -1) data[p2].childInequality = std::max(data[p2].childInequality, al2); } if (p1 != -1) { if (--data[p1].indegree == 0) toprocess.push_back(p1); } if (p2 != -1) { if (--data[p2].indegree == 0) toprocess.push_back(p2); } } for (int i = 0; i < n; i++) { if (data[i].outdegree == 0) toprocess.push_back(i); } while (!toprocess.empty()) { int cur = toprocess.front(); toprocess.pop_front(); int p1 = creatures[cur].p1; int p2 = creatures[cur].p2; if (mask & (1ULL << cur)) std::swap(p1, p2); if (data[cur].alleles[1] < 0) { char al = -data[cur].alleles[1]; if (p2 == -1) data[cur].alleles[1] = al; else { if (data[p2].alleles[0] >= al) data[cur].alleles[1] = data[p2].alleles[0]; else if (data[p2].alleles[1] >= al) data[cur].alleles[1] = data[p2].alleles[1]; else return false; // probably unreachable? } } for (auto it : data[cur].children) { if (--data[it].outdegree == 0) toprocess.push_back(it); } } sol.clear(); for (int i = 0; i < n; i++) { sol.push_back(std::min(data[i].alleles[0], data[i].alleles[1])); sol.push_back(std::max(data[i].alleles[0], data[i].alleles[1])); } return true; } int main() { int n; std::cin >> n; std::vector creatures(n); for (int i = 0; i < n; i++) { int p1, p2; std::cin >> p1 >> p2; creatures[i].p1 = p1 - 1; creatures[i].p2 = p2 - 1; std::cin >> creatures[i].color; } bool ok = false; std::string best; uint64_t combos = (1ULL << n); for (uint64_t mask = 0; mask < combos; mask++) { std::string sol; if (tryCase(creatures, mask, sol)) { if (!ok) { ok = true; best = sol; } else best = std::min(best, sol); } } if (!ok) std::cout << -1 << std::endl; else { for (int i = 0; i < n; i++) { std::cout << best[2 * i] << best[2 * i + 1] << std::endl; } } }