Skip to Content

Coloring Game

Editorial oficial (C++) 

Explicación

Primero, determinamos si el grafo es bipartito.

Si el grafo no es bipartito, Alice puede elegir siempre los mismos dos colores. Como el grafo no es bipartito, es imposible que Bob coloree el grafo con solo dos colores de modo que no haya nodos adyacentes del mismo color. Así, Alice siempre gana.

Si el grafo es bipartito, se puede partir en dos grupos tales que no hay aristas que conecten nodos dentro de un mismo grupo. Bob puede asignar a los nodos del grupo 1 el color 1, y a los del grupo 2 el color 2. Cuando un grupo queda completo, Bob puede usar el color 3 o el color original en el grupo que falta, lo que garantiza que nodos de grupos distintos siempre tendrán colores distintos. Por lo tanto, si el grafo es bipartito, Bob siempre gana.

Implementación

Complejidad temporal: O(N)\mathcal{O}(N)

#include <bits/stdc++.h> using namespace std; void solve() { int n, m; cin >> n >> m; vector<vector<int>> adj(n); // Armamos el grafo for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; adj[--u].push_back(--v); adj[v].push_back(u); } vector<int> c(n, -1); c[0] = 0; bool notBipartite = false; auto dfs = [&](auto &&self, int nd) -> void { for (int x : adj[nd]) { if (c[x] == -1) { c[x] = !c[nd]; self(self, x); } else if (c[x] == c[nd]) { notBipartite = true; return; } } }; // DFS para chequear si el grafo es bipartito dfs(dfs, 0); if (notBipartite) { // Si no es bipartito, gana Alice int gb; cout << "Alice" << endl; for (int i = 0; i < n; i++) { cout << 1 << " " << 2 << endl; cin >> gb >> gb; } } else { // El grafo es bipartito, gana Bob cout << "Bob" << endl; array<vector<int>, 2> g; for (int i = 0; i < n; i++) { g[c[i]].push_back(i); } for (int i = 0; i < n; i++) { int a, b; cin >> a >> b; a--, b--; if (a > b) { swap(a, b); } if (g[a].size()) { cout << g[a].back() + 1 << " " << a + 1 << endl; g[a].pop_back(); } else { cout << g[!a].back() + 1 << " " << b + 1 << endl; g[!a].pop_back(); } } } } int main() { int t; cin >> t; while (t--) { solve(); } }
import sys def solve(): data = sys.stdin n, m = map(int, data.readline().split()) # Armamos el grafo adj = [[] for _ in range(n)] for _ in range(m): u, v = map(int, data.readline().split()) u -= 1 v -= 1 adj[u].append(v) adj[v].append(u) c = [-1] * n c[0] = 0 not_bipartite = False # Determinamos si el grafo es bipartito stack = [0] while stack and not not_bipartite: nd = stack.pop() for x in adj[nd]: if c[x] == -1: c[x] = c[nd] ^ 1 stack.append(x) elif c[x] == c[nd]: not_bipartite = True break if not_bipartite: # Si no es bipartito, gana Alice print("Alice", flush=True) for _ in range(n): print(1, 2, flush=True) data.readline() else: # Si es bipartito, gana Bob print("Bob", flush=True) g = [[], []] for i in range(n): g[c[i]].append(i) for _ in range(n): a, b = map(int, data.readline().split()) a -= 1 b -= 1 if a > b: a, b = b, a if g[a]: v = g[a].pop() print(v + 1, a + 1, flush=True) else: v = g[a ^ 1].pop() print(v + 1, b + 1, flush=True) def main(): t = int(sys.stdin.readline()) for _ in range(t): solve() if __name__ == "__main__": main()
import java.io.*; import java.util.*; public class ColoringGame { static List<Integer>[] adj; static int[] color; static boolean bad; public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); int t = Integer.parseInt(br.readLine().trim()); while (t-- > 0) { StringTokenizer st = new StringTokenizer(br.readLine()); int n = Integer.parseInt(st.nextToken()); int m = Integer.parseInt(st.nextToken()); adj = new ArrayList[n]; for (int i = 0; i < n; i++) adj[i] = new ArrayList<>(); // Armamos el grafo for (int i = 0; i < m; i++) { st = new StringTokenizer(br.readLine()); int u = Integer.parseInt(st.nextToken()) - 1; int v = Integer.parseInt(st.nextToken()) - 1; adj[u].add(v); adj[v].add(u); } color = new int[n]; Arrays.fill(color, -1); color[0] = 0; bad = false; // Determinamos si el grafo es bipartito ArrayDeque<Integer> stack = new ArrayDeque<>(); stack.push(0); while (!stack.isEmpty() && !bad) { int nd = stack.pop(); for (int x : adj[nd]) { if (color[x] == -1) { color[x] = color[nd] ^ 1; stack.push(x); } else if (color[x] == color[nd]) { bad = true; break; } } } if (bad) { // Si el grafo no es bipartito, gana Alice out.println("Alice"); out.flush(); for (int i = 0; i < n; i++) { out.println("1 2"); out.flush(); br.readLine(); } } else { // Si el grafo es bipartito, gana Bob out.println("Bob"); out.flush(); ArrayList<Integer>[] g = new ArrayList[2]; g[0] = new ArrayList<>(); g[1] = new ArrayList<>(); for (int i = 0; i < n; i++) { g[color[i]].add(i); } for (int i = 0; i < n; i++) { st = new StringTokenizer(br.readLine()); int a = Integer.parseInt(st.nextToken()) - 1; int b = Integer.parseInt(st.nextToken()) - 1; if (a > b) { int tmp = a; a = b; b = tmp; } if (!g[a].isEmpty()) { int v = g[a].remove(g[a].size() - 1); out.println((v + 1) + " " + (a + 1)); } else { int v = g[a ^ 1].remove(g[a ^ 1].size() - 1); out.println((v + 1) + " " + (b + 1)); } out.flush(); } } } out.flush(); } }