https://www.luogu.org/problem/show?pid=2819
题目背景
给定无向连通图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)。
输出格式:
程序运行结束时,将计算出的不同的着色方案数输出。
输入输出样例
输入样例#1:
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5
输出样例#1:
48
说明
n<=100;k<=2500;
在n很大时保证k足够大。
保证答案不超过20000。
1 #include <algorithm> 2 #include <iostream> 3 4 using namespace std; 5 6 int n,k,m,fx,fy,ans; 7 int color[2505]; 8 int burn[2505][2505]; 9 10 bool judge(int x,int col) 11 { 12 //枚举每个点的染色情况 13 for(int i=1;i<=n;i++) 14 { 15 //不看当前点 16 if(x==i) continue; 17 //两个点首先要连接,如果颜色相同的话,那么就无法染编号为i的颜色 18 if(burn[x][i]==1&&color[i]==col) 19 return 0; 20 } 21 //两点不连接或者连到的点颜色不与编号为i的点的颜色相同,就可以染色 22 return 1; 23 } 24 25 void DFS(int now) 26 { 27 //如果当前染够了n个点,退出,找下一个方案;; 28 if(now==n+1) 29 { 30 ans++; 31 return ; 32 } 33 //枚举可以染上的颜色的编号 34 for(int i=1;i<=m;i++) 35 { 36 //如果当前的点没有染色,就判断它是否可以染编号为i的颜色 37 if(!color[now]&&(judge(now,i))) 38 { 39 //染上枚举到的颜色 40 color[now]=i; 41 //染下一个点 42 DFS(now+1); 43 //如果始终无法染够n个点,或者完成了一种方案,回溯;; 44 color[now]=0; 45 } 46 } 47 } 48 49 int main() 50 { 51 cin>>n>>k>>m; 52 for(int i=1;i<=k;i++) 53 { 54 cin>>fx>>fy; 55 //首先,把图建出来;;; 56 burn[fx][fy]=burn[fy][fx]=1; 57 } 58 DFS(1); 59 //从第一个点开始找;; 60 cout<<ans; 61 return 0; 62 }
无解析:
#include <algorithm> #include <iostream> using namespace std; int n,k,m,fx,fy,ans; int color[2505]; int burn[2505][2505]; bool judge(int x,int col) { for(int i=1;i<=n;i++) { if(x==i) continue; if(burn[x][i]==1&&color[i]==col) return 0; } return 1; } void DFS(int now) { if(now==n+1) { ans++; return ; } for(int i=1;i<=m;i++) { if(!color[now]&&(judge(now,i))) { color[now]=i; DFS(now+1); color[now]=0; } } } int main() { cin>>n>>k>>m; for(int i=1;i<=k;i++) { cin>>fx>>fy; burn[fx][fy]=burn[fy][fx]=1; } DFS(1); cout<<ans; return 0; }