1080. Map Colouring
Memory Limit: 16 MB
Input
Output
Sample
input | output |
---|---|
3 2 0 3 0 0 |
010 |
Problem Source: Winter Mathematical Festival Varna '2001 Informatics Tournament
这道题目给出地图上的 N 个国家,这个地图只有一块大陆,没有孤岛。要求写一个程序使用红色和蓝色这两种颜色给地图上的所有国家着色,且相邻的国家使用不同的颜色。
给定的输入的第一行是地图上的国家的数目 N。后面跟着 N 行,每一行表示第 i 个国家的邻国的编号列表,该列表仅列出编号比 i 大的国家,以 0 结束。
要求程序依次输出各个国家的着色,0 代表红色,1 代表蓝色,且第一个国家着红色。如果没有合适的着色方案,就输出 -1。
2 using System.IO;
3 using System.Collections.Generic;
4
5 namespace Skyiv.Ben.Timus
6 {
7 // http://acm.timus.ru/problem.aspx?space=1&num=1080
8 sealed class T1080
9 {
10 static void Main()
11 {
12 Dictionary<int,object>[] map = Read(Console.In);
13 bool?[] color = new bool?[map.Length];
14 color[0] = false;
15 if (!Search(map, color, 0)) Console.Write(-1);
16 else foreach (bool c in color) Console.Write(c ? 1 : 0);
17 }
18
19 static Dictionary<int,object>[] Read(TextReader reader)
20 {
21 Dictionary<int,object>[] map = new Dictionary<int,object>[int.Parse(reader.ReadLine())];
22 for (int i = 0; i < map.Length; i++) map[i] = new Dictionary<int,object>();
23 for (int i = 0; i < map.Length; i++)
24 {
25 string[] ss = reader.ReadLine().Split();
26 for (int k = 0; k < ss.Length - 1; k++)
27 {
28 int j = int.Parse(ss[k]) - 1;
29 map[i][j] = map[j][i] = null;
30 }
31 }
32 return map;
33 }
34
35 static bool Search(Dictionary<int,object>[] map, bool?[] color, int k)
36 {
37 foreach (int v in map[k].Keys)
38 if (color[v] == null)
39 {
40 color[v] = !color[k];
41 if (!Search(map, color, v)) return false;
42 }
43 else if (color[v] == color[k]) return false;
44 return true;
45 }
46 }
47 }
在上述程序中,第 10 到 17 行是 Main 方法,首先调用 Read 方法读取输入到 map 数组中(第 12 行),然后分配颜色数组 color (第 13 行),该数组的数据类型是可空布尔值,null 值表示该国家尚未着色,false 表示红色,true 表示蓝色。接着将第一个国家着红色(第 14 行)。第 15 行调用 Search 方法寻找着色方案,如果没有找到合适的着色方案就输出 -1,否则就依次输出各个国家的着色(第 16 行)。
第 19 到 33 行的 Read 方法读取输入。第 21 行读取国家的数目并分配表示地图的 map 数组,该数组的数据类型是 Dictionary<int,object>,其索引键表示所有邻国的编号。第 23 行开始的循环依次读取输入。注意第 29 行设置所有的邻国,而不是只有编号更大的邻国。
第 35 到 45 行的 Search 方法使用深度优先搜索算法来寻找着色方案,其中参数 k 表示国家编号。第 37 行开始的循环遍历第 k 个国家的所有邻国。第 38 行判断如果该邻国尚未着色,就着另一种颜色(第 40 行),并使用该邻国的编号 v 行为参数递归调用自身继续搜索(第 41 行)。第 43 行判断如果该邻国已经着相同颜色,就返回搜索失败。否则继续搜索,直到遍历所有邻国。
著名的 四色定理 是说只需四种颜色就一定可以给上述的地图着色,这也是第一个主要由计算机证明的定理。上述程序如果作一些修改,应该可以用于验证(不是证明)四色定理。
返回目录