题目背景
给定无向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果有一种着色法使G中每条边的2个顶点着不同颜色,则称这个图是m可着色的。图的m着色问题是对于给定图G和m种颜色,找出所有不同的着色法。
题目描述
对于给定的无向连通图G和m种不同的颜色,编程计算图的所有不同的着色法。
输入格式
第1行有3个正整数n,k 和m,表示给定的图G有n个顶点和k条边,m种颜色。顶点编号为1,2,…,n。接下来的k行中,每行有2个正整数u,v,表示图G 的一条边(u,v)。
输出格式
程序运行结束时,将计算出的不同的着色方案数输出。
输入样例
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
输出样例
48
说明
n<=100;k<=2500;
在n很大时保证k足够大。
保证答案不超过20000。
题解
别的剪枝不多说了。在这一题中,我们要搜索的起点其实只用搜一种颜色,最后输出的时候再乘上$m$即可(乘法原理)。
#include#define MAX_N (100 + 5)#define MAX_K (2500 + 5)#define MAX_M (2500 + 5)using namespace std;struct Edge{ int to; int next;};int n, k, m;int h[MAX_N], tot;Edge e[MAX_K + MAX_K];int c[MAX_N][MAX_M];int ans;inline void Add_Edge(int u, int v){ e[++tot].to = v; e[tot].next = h[u]; h[u] = tot; return;}void DFS(int u){ if(u > n) { ++ans; return; } for(register int i = 1; i <= m; ++i) { if(c[u][i]) continue; for(register int j = h[u]; j; j = e[j].next) { ++c[e[j].to][i]; } DFS(u + 1); for(register int j = h[u]; j; j = e[j].next) { --c[e[j].to][i]; } } return;}int main(){ cin >> n >> k >> m; int u, v; for(register int i = 1; i <= k; ++i) { cin >> u >> v; Add_Edge(u, v); Add_Edge(v, u); } for(register int i = h[1]; i; i = e[i].next) { ++c[e[i].to][1]; } DFS(2); cout << ans * m; return 0;}