1、图的m着色问题:
1 /* 2 *问题描述:给定无向连通图G和m种不同的颜色。用这些颜色为图G的各个顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的两个顶点着不同的颜色。 3 * 这个问题是图的m可着色判定问题。若一个图最少需要m中颜色才能使图中每条边连接的2个顶点着不同的颜色,则称这个数m为该图的色数。 4 *算法分析:给定图G=(V,E)和m中颜色,如果这个图不是m可着色,给出否定回答;如果这个图是m可着色的,找出所有不同的着色法。 5 * 回溯法+子集树 6 * 问题的解空间可表示为一棵高度为n+1的完全m叉树,解空间树的第i层中每一个结点都有m个儿子,每个儿子相应于x[i]的m个可能的着色之一,第n+1层结点均为叶结点。 7 *算法效率:图m可着色问题的解空间树中的内结点个数是m^i之和(i从0到n-1),在最坏的情况下,用ok检查当前扩展结点的每一个儿子所相应的颜色的可用性需耗时O(mn)。 8 因此回溯总的耗时为mn(m^n-1)/(m-1)=O(nm^n) 9 *附 注:初始化无向图矩阵的时候对角线赋值为0!!! 10 *Author:xymaqingxiang 11 *Time:2014--5-22 12 */ 13 14 #include <fstream> 15 #include <iostream> 16 #include <stdlib.h> 17 #include <conio.h> 18 using namespace std; 19 20 #define MAX_v 50 //定义一个最大顶点个数 21 typedef struct{ 22 int a[MAX_v][MAX_v]; //无向图G的邻接矩阵 23 int n; //无向图G的顶点数 24 int m; //无向图G的颜色数 25 int x[50]; //当前解 26 long sum;//当前已找到的可m着色的方案数 27 }MC; 28 29 void Creat(MC &G); 30 void Backtrack(MC &G,int t); 31 32 void Creat(MC &G){ 33 int i,j; 34 ifstream fin("data.txt"); 35 if (!fin) 36 { 37 cout<<"不能打开文件:"<<"data.txt"<<endl; 38 exit(1); 39 } 40 fin>>G.n; 41 fin>>G.m; 42 for (int i=1;i<=G.n;i++) 43 for (int j=1;j<=G.n;j++) 44 fin>>G.a[i][j]; 45 for(i=1;i<=G.n;i++) //初始化 46 { 47 G.x[i]=0; 48 G.sum=0; 49 } 50 cout<<"———回溯法求解图的m着色问题———"<<endl; 51 cout<<"输入初始化无向图矩阵为:"<<endl; //初始化 52 for(i=1;i<=G.n;i++) 53 { 54 for(j=1;j<=G.n;j++) 55 cout<<G.a[i][j]<<" "; 56 cout<<endl; 57 } 58 cout<<"输入初始化无向图顶点数为:"<<" "; //初始化 59 cout<<G.n<<endl; 60 cout<<"输入初始化无向图着色数为:"<<" "; //初始化 61 cout<<G.m<<endl; 62 } 63 64 bool ok(MC &G,int k) 65 { 66 for(int j=1;j<=G.n;j++) 67 if(G.a[k][j]==1&&G.x[j]==G.x[k]) //先后顺序——先判断是否相邻,然后判断颜色是否相同 68 return false; 69 return true; 70 } 71 72 void Backtrack(MC &G,int t){ 73 if (t>G.n){ //output()阶段 74 G.sum++; 75 for (int j=1; j<=G.n; j++) 76 cout<<G.x[j]<<' '; 77 cout<<endl; 78 } 79 else 80 { 81 for(int i=1;i<=G.m;i++) 82 { 83 G.x[t]=i; 84 if(ok(G,t)) 85 Backtrack(G,t+1); 86 G.x[t]=0; //递归回退时返回上一层,着色赋初值0 87 } 88 } 89 } 90 91 int main(){ 92 MC G; 93 Creat(G); 94 Backtrack(G,1); 95 getch(); 96 }