bool fill_room(int rooms, int flavors, IntSet V[], IntSet F[], IntVec C[], IntVec &pillars, int room) { bool result = true; IntSet::const_iterator it; for (it = V[room].begin(); it != V[room].end(); ++it) { int pillar = *it; if (pillars[pillar] > 0) { continue; } IntSet s; int i; for (i = 0; i < (int)C[pillar].size(); ++i) { s.insert(pillars[C[pillar][i]]); } for (i = 1; i <= flavors; ++i) { if (F[room].count(i) <= 0 && s.count(i) <= 0) { set_flavor(rooms, V, F, pillars, pillar, i); break; } } if (i > flavors) { for (i = 1; i <= flavors; ++i) { if (s.count(i) <= 0) { set_flavor(rooms, V, F, pillars, pillar, i); break; } } if (i > flavors) { result = false; } } } return result; }
static bool SetsAreEqual(IntSet& am, IntSet& bm) { bool equal = true; if (am.count() != bm.count()) { equal = false; fprintf(stderr, "A.count() == %u and B.count() == %u\n", am.count(), bm.count()); } for (auto iter = am.iter(); !iter.done(); iter.next()) { if (!bm.has(iter.get())) { equal = false; fprintf(stderr, "B does not have %x which is in A\n", iter.get()); } } for (auto iter = bm.iter(); !iter.done(); iter.next()) { if (!am.has(iter.get())) { equal = false; fprintf(stderr, "A does not have %x which is in B\n", iter.get()); } } return equal; }
static bool SetsAreEqual(IntSet& am, IntSet& bm) { bool equal = true; if (am.count() != bm.count()) { equal = false; fprintf(stderr, "A.count() == %u and B.count() == %u\n", am.count(), bm.count()); } for (IntSet::Range r = am.all(); !r.empty(); r.popFront()) { if (!bm.has(r.front())) { equal = false; fprintf(stderr, "B does not have %x which is in A\n", r.front()); } } for (IntSet::Range r = bm.all(); !r.empty(); r.popFront()) { if (!am.has(r.front())) { equal = false; fprintf(stderr, "A does not have %x which is in B\n", r.front()); } } return equal; }
bool solve(int N, int M, IIVec &walls, int &flavors, IntVec &pillars) { IntSet V[2000]; // vertexes in a room IntSet F[2000]; // flavors in a room IntVec C[2001]; // vertex connection int i, j; for (i = 0; i < N; ++i) { V[0].insert(i); } int rooms = 1; for (i = 0; i < N; ++i) { C[i].push_back((i-1+N)%N); C[i].push_back((i+1)%N); } for (i = 0; i < (int)walls.size(); ++i) { int s = min(walls[i].first, walls[i].second) - 1; int e = max(walls[i].first, walls[i].second) - 1; for (j = 0; j < rooms; ++j) { if (V[j].count(s) > 0 && V[j].count(e) > 0) { break; } } if (j >= rooms) { // error return false; } IntSet a, b; a.insert(s); a.insert(e); b.insert(s); b.insert(e); bool f = false; IntSet::const_iterator it; for (it = V[j].begin(); it != V[j].end(); ++it) { if (!f) { a.insert(*it); } else { b.insert(*it); } if (*it == s || *it == e) { f = !f; } } V[j] = a; V[rooms++] = b; C[s].push_back(e); C[e].push_back(s); } flavors = N; for (i = 0; i < rooms; ++i) { flavors = min((int)V[i].size(), flavors); } // fill the first room { int flavor = 1; IntSet::const_iterator it; for (it = V[0].begin(); it != V[0].end(); ++it) { int pillar = *it; if (flavor <= flavors) { set_flavor(rooms, V, F, pillars, pillar, flavor); } else { // fill with different color IntSet s; for (i = 0; i < (int)C[pillar].size(); ++i) { s.insert(pillars[C[pillar][i]]); } for (i = 1; ; ++i) { if (s.count(i) <= 0) { set_flavor(rooms, V, F, pillars, pillar, i); break; } } } ++flavor; } } int filled_rooms, room; for (filled_rooms = 1; filled_rooms < N; ++filled_rooms) { bool found = false; for (room = 0; room < rooms; ++room) { int c = 0; IntSet::const_iterator it; for (it = V[room].begin(); it != V[room].end(); ++it) { if (pillars[*it] > 0) { ++c; } } if (c >= 2 && c < (int)V[room].size()) { found = true; break; } } if (!found) { break; } fill_room(rooms, flavors, V, F, C, pillars, room); } for (i = 0; i < rooms; ++i) { if ((int)F[i].size() < flavors) { return false; } } for (i = 0; i < N; ++i) { if (pillars[i] <= 0 || pillars[i] > flavors) { return false; } } return true; }