第五章 图着色问题
来源:互联网 发布:淘宝自己组装iphone 编辑:程序博客网 时间:2024/06/15 05:03
图着色问题是最著名的NP-完全问题,由此还引出了著名的四色定理,四色猜想还曾是一百年来历史上最难的数学难题之一,当然,我不是学数学的,对这些猜想证明一窍不通,也不感冒,但是,图着色问题作为一道算法题目确是很值得研究的,所以作为一名的大学生程序员的我,把它另作一章是无可厚非的
问题描述自不必多说,对于这个问题,我首先想到的就是用搜索+回溯的思想,一个一个的去试,先拿1种颜色图,不行再加一种,等等,代码先贴上
#include <iostream>#include <cstring>using namespace std;#define N 8//表示一张图int g[][N]={{0,1,1,1,0,0,1,0},{1,0,1,1,1,0,0,0},{1,1,0,0,1,1,0,0},{1,1,0,0,1,0,1,0},{0,1,1,1,0,1,1,1},{0,0,1,0,1,0,0,1},{1,0,1,1,1,0,0,1},{0,0,0,0,1,1,1,0}};//标记的颜色int color[N];//检查是否有邻居标记过同一种颜色int ok(int t){for(int i=0;i<N;i++)if(i!=t&&g[t][i]&&color[t]==color[i])return 0;return 1;}//试着用m种颜色进行标记bool traceback(int t,int m){if(t>=N)return true;for(int i=1;i<=m;i++){color[t]=i;if(ok(t)&&traceback(t+1,m))return true;color[t]=0;}return false;}int main(){#ifndef wangchuanfreopen("C:\\in.txt","r",stdin);#endif // !wangchuanmemset(color,0,sizeof(color));for(int j=1;j<=4;j++){if(traceback(0,j)){for(int i=0;i<N;i++){cout<<"第"<<i<<"点标记颜色"<<color[i]<<endl;}break;}}return 0;}
还有一种Welch Powell法,实质上是一种贪心策略
a).将G的结点按照度数递减的次序排列.
b).用第一种颜色对第一个结点着色,并按照结点排列的次序
对与前面着色点不邻接的每一点着以相同颜色.
c).用第二种颜色对尚未着色的点重复步骤b).用第三种颜色
继续这种作法, 直到所有点着色完为止.
//图着色问题//WelchPowell法#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define N 8//表示一张图int g[][N]={{0,1,1,1,0,0,1,0},{1,0,1,1,1,0,0,0},{1,1,0,0,1,1,0,0},{1,1,0,0,1,0,1,0},{0,1,1,1,0,1,1,1},{0,0,1,0,1,0,0,1},{1,0,1,1,1,0,0,1},{0,0,0,0,1,1,1,0}};struct node{int color;//标记的颜色int degree;//节点的度数(出度或入度)int index;//因为要排序,所以先要记录节点所在位置bool operator<(node &t){return degree>t.degree;}}Node[N];void WelchPowell(){ sort(Node,Node+N);int k = 0;//K 代表第几种颜色while (true) {k++;int i;for (i = 0; i < N; i++){//先找到第一个未着色的节点if (Node[i].color == 0) {Node[i].color = k;break;}}if (i == N)//循环退出的条件,所有节点都已着色break;//再把所有不和该节点相邻的节点着相同的颜色for(int j=0; j<N; j++){if(Node[j].color ==0 &&g[Node[i].index][Node[j].index] == 0&&i!=j)Node[j].color = k;}}}int main(){#ifndef WANGCHUANfreopen("C:\\in.txt","r",stdin);#endif // !WANGCHUANfor(int i=0;i<N;i++){Node[i].index=i;Node[i].color=0;Node[i].degree=0;for(int j=0;j<N;j++){if(g[i][j])Node[i].degree++;}}WelchPowell();for (int i=0; i<N; i++)cout<<"第"<<Node[i].index<<"点标记颜色"<< Node[i].color <<endl;return 0;}
还有一种简单的贪心算法,先拿一种颜色标记尽量多的点,如果还有点没标,再拿另一种颜色标记,如此反复
//图着色问题//贪心法#include <iostream>#include <cstring>#include <algorithm>using namespace std;#define N 8//表示一张图int g[][N]={{0,1,1,1,0,0,1,0},{1,0,1,1,1,0,0,0},{1,1,0,0,1,1,0,0},{1,1,0,0,1,0,1,0},{0,1,1,1,0,1,1,1},{0,0,1,0,1,0,0,1},{1,0,1,1,1,0,0,1},{0,0,0,0,1,1,1,0}};int color[N];//检查是否有邻居标记过颜色kint ok(int t,int k){for(int i=0;i<N;i++)if(i!=t&&g[t][i]&&k==color[i])return 0;return 1;}void Greedy(){color[0]=1;//先给节点0着颜色1int k = 0;//K 代表第几种颜色while (true) {k++;//如果所有顶点均着色,退出循环int i;for(i=1;i<N;i++)if(!color[i])break;if(i==N)break;//for(int i=1;i<N;i++){if(color[i])continue;//判断i点能否着颜色k,即i的邻居节点没有着颜色k的if(ok(i,k))color[i]=k;}}}int main(){#ifndef WANGCHUANfreopen("C:\\in.txt","r",stdin);#endif // !WANGCHUANmemset(color,0,sizeof(color));Greedy();for (int i=0; i<N; i++)cout<<"第"<<i<<"点标记颜色"<< color[i] <<endl;return 0;}
当然还有更加高级的蚁群算法,但是不会写实现代码,等会写的时候再贴上吧
王川
2014/02/17
0 0
- 第五章 图着色问题
- 第五章【回溯法】最大团问题和图的m着色问题
- 算法设计与分析:第五章 回溯法 5.3图的着色问题
- m图着色问题
- 区间图着色问题
- 区间图着色问题
- 回溯 图着色问题
- 图的着色问题
- 图的着色问题
- 图着色问题
- m图着色问题
- 图的着色问题
- 区间图着色问题
- 图着色问题
- 区间图着色问题
- 图最少着色问题
- 图的着色问题:
- 图着色问题
- Class的getCanonicalName和getSimpleName getName的区别与应用
- poj 1830 开关问题(高斯消元)
- Java 单例模式详解
- PEP-8 中文翻译
- hdu 1789 正统的贪心问题!!!想了好长时间!
- 第五章 图着色问题
- 【C#小知识】C#中一些易混淆概念总结(八)---------解析接口
- 第八十一天【java虐我千百遍,我待java如初恋】
- MySQL replace into 用法
- mysql系列:触发器使用
- system verilog的杂乱无章(一)
- InnoDB表与索引结构相关知识整理
- jquery 使用方法
- Spring源码阅读入门指引