import java.util.Random;

public class Coloring {

	int minColors;
	int[] bestColoring;

	public int minColors(boolean[][] graph) {
		int n = graph.length;
		bestColoring = new int[n];
		int[] id = new int[n + 1];
		int[] deg = new int[n + 1];
		for (int i = 0; i <= n; i++)
			id[i] = i;
		bestColoring = new int[n];
		int res = 1;
		for (int from = 0, to = 1; to <= n; to++) {
			int best = to;
			for (int i = to; i < n; i++) {
				if (graph[id[to - 1]][id[i]])
					++deg[id[i]];
				if (deg[id[best]] < deg[id[i]])
					best = i;
			}
			int t = id[to];
			id[to] = id[best];
			id[best] = t;
			if (deg[id[to]] == 0) {
				minColors = n + 1;
				dfs(graph, id, new int[n], from, to, from, 0);
				from = to;
				res = Math.max(res, minColors);
			}
		}
		return res;
	}

	void dfs(boolean[][] graph, int[] id, int[] coloring, int from, int to, int cur, int usedColors) {
		if (usedColors >= minColors)
			return;
		if (cur == to) {
			for (int i = from; i < to; i++)
				bestColoring[id[i]] = coloring[i];
			minColors = usedColors;
			return;
		}
		boolean[] used = new boolean[usedColors + 1];
		for (int i = 0; i < cur; i++)
			if (graph[id[cur]][id[i]])
				used[coloring[i]] = true;
		for (int i = 0; i <= usedColors; i++) {
			if (!used[i]) {
				int tmp = coloring[cur];
				coloring[cur] = i;
				dfs(graph, id, coloring, from, to, cur + 1, Math.max(usedColors, i + 1));
				coloring[cur] = tmp;
			}
		}
	}

	// random test
	public static void main(String[] args) {
		Random rnd = new Random(1);
		for (int step = 0; step < 1000; step++) {
			int n = rnd.nextInt(10) + 1;
			boolean[][] g = new boolean[n][n];
			for (int i = 0; i < n; i++)
				for (int j = 0; j < i; j++)
					if (rnd.nextBoolean()) {
						g[i][j] = true;
						g[j][i] = true;
					}
			int res1 = new Coloring().minColors(g);
			int res2 = colorSlow(g);
			if (res1 != res2)
				throw new RuntimeException();
		}
	}

	static int colorSlow(boolean[][] g) {
		int n = g.length;
		for (int allowedColors = 1; ; allowedColors++) {
			long colors = 1;
			for (int i = 0; i < n; i++)
				colors *= allowedColors;
			m1:
			for (long c = 0; c < colors; c++) {
				int[] col = new int[n];
				long cur = c;
				for (int i = 0; i < n; i++) {
					col[i] = (int) (cur % allowedColors);
					cur /= allowedColors;
				}
				for (int i = 0; i < n; i++)
					for (int j = 0; j < i; j++)
						if (g[i][j] && col[i] == col[j])
							continue m1;
				return allowedColors;
			}
		}
	}
}
