回溯法 图着色问题

来源:互联网 发布:优酷不能登录淘宝账号 编辑:程序博客网 时间:2024/05/22 07:06

问题:

给定 无向连通图G=(V,E) 和 c种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。如果一个图最少需要c种颜色才能使图中每条边连接的2个顶点着不同颜色,则称c为该图的色数。
著名的 四色定理 就是指每个平面地图都可以只用四种颜色来染色,而且没有两个邻接的区域颜色相同。

求:给定图的顶点v,顶点间的边邻接关系graph[][],颜色的数量c,一共有多少种着色方法?

这里写图片描述

对于上面这图,颜色数量为4,顶点数为5,求得的解答树如下:

这里写图片描述
ps:解答树只给出部分

分析:

当cur = 3时,即填第3个顶点的颜色时,(1,2,1,*,)表示第1个顶点着第1中颜色,第2个顶点着第2个颜色,第3个顶点着第1个颜色,但是根据邻接表,顶点1和3是相邻的,因此此节点的子树没有解,因此用剪枝函数剪去

(1,2,2,*,)表示第1个顶点着第1个颜色,第2个顶点着第2个颜色,第3个顶点着第1个颜色,但是根据邻接表,顶点1和2是相邻的,因此此节点的子树没有解,因此用剪枝函数剪去

(1,2,3,1,*)表示第1个顶点着第1个颜色,第2个顶点着第2个颜色,第3个顶点着第3个颜色,第4个顶点着第1个颜色,顶点1和顶点4不是相邻的,因此可以都使用第1个个颜色,因此按照该节点的子树进行下一层的dfs

最终得出:(1,2,3,1,*)下的解有(1,2,3,1,3),(1,2,3,1,4),(1,2,3,1,5)

…..以此类推

分析时的规律:

  1. cur:代表当前层,当前行,cur+1表示去到下一层或下一行;
  2. for中的i:代表当前列,i++表示横移到右一列或是右一兄弟节点
  3. 要分清用什么填什么,(用i填cur)图着色问题这里就是用颜色填顶点位置

代码实现

#include<iostream>using namespace std;int v,e,graph[100][100];//v顶点数, e边数, graph图的邻接矩阵 int c,color[100];//c颜色数  color当前边的颜色 int sum = 0;//着色方法的数目 //判断当前位置的颜色是否和相邻位置颜色重复 bool ok(int cur){    for(int i=1; i<=v; i++){        if(graph[cur][i] && color[cur] == color[i]){//如果坐标(cur,i)相邻 且 cur的颜色和i的颜色相同             return false;         }    }    return true;}void backtrace(int cur){    if(cur > v){        sum++;    } else {        for(int i=1; i<=c; i++){//分别为cur位置尝试第i中颜色             color[cur] = i;//表示cur位置图上第i种颜色             if(ok(cur)){                backtrace(cur+1);            }            color[cur] = 0;        }    }}int main(){    cout << "输入顶点数和颜色数量:" ;    cin >> v >> c;    cout << endl;    //输入邻接矩阵     for(int i=1; i<=v; i++){        for(int j=1; j<=v; j++){            cin >> graph[i][j];        }    }    backtrace(1);    cout << sum;}

样例输入:
5 4
0 1 1 1 0
1 0 1 1 1
1 1 0 1 0
1 1 1 0 1
0 1 0 1 0

样例输出:
48

0 0
原创粉丝点击