題目背景
給定無向連通圖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 <iostream> #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; }