一、问题分析
把每一个区域抽象为一个点,把区域相邻用一条边连接,给图上每一点上色,保证该点颜色与相邻点颜色不同,保证颜色的总数最少。给定一个无向图G=(V, E),其中V为顶点集合,E为边集合,图着色问题即为将V分为K个颜色组,每个组形成一个独立集,即其中没有相邻的顶点。其优化版本是希望获得最小的K值。
二、算法选择
在解决这个问题时,回溯法可以用来遍历所有可能的着色方案,并确定最佳的颜色方案。回溯法依据当前已经着色的领域,向剩下的领域分配不同的颜色,如果领域间的相邻关系不符合要求,则撤回刚才的着色方案,并重新分配颜色。一旦找到符合要求的着色方案,则停止搜索,并输出最优解。
三、设计思路
利用回溯法,先从最少的颜色:1,开始向后尝试,无论如何不会超过n种颜色,因位只有n个点,所以就for (1~n)尝试,对于每种颜色从1号点开始染色
对于图G,我们可以使用深度优先搜索(DFS)算法来遍历它。在DFS算法中,我们从一个顶点出发沿着图中的边一直走到不能再往下走为止,然后换另一个顶点继续走,直到遍历完整个图。
求解
邻接表存图
printf("输入点数n, 边数m\n");
cin >> n >> m;
printf("输入%d条无向边, 每行两个整数a,b,表示a和b之间有一条无向边\n\n",m);
while (m -- )
{
scanf("%d%d", &a, &b);
G[a].push_back(b), G[b].push_back(a);
}
判断函数j
bool dfs(int cur, int k)
{
if(cur > n)
{
printf("染色成功\n\n");
printf("最少需要%d种颜色\n\n", k);
printf("接下来分别是每个点染上的颜色\n\n");
for(int i = 1; i <= n; i ++ )
{
printf("第%d个点的颜色是%d ", i, color[i]);
if (i % 5 == 0) printf("\n");
}
printf("\n\n方案输出完毕");
printf("\n");
return true ;
}
if (!puted[k]) printf("正在尝试能否用%d种颜色为图染色\n", k), puted[k] = true;
printf("目前正在给点%d染色\n", cur);
for(int clr = 1; clr <= k; clr ++ )
{
color[cur] = clr;
if(check(cur)) { printf("点%d成功染上第%d钟颜色\n\n", cur, clr); return dfs(cur + 1, k); }
else printf("对于%d点染第%d种颜色出现冲突\n\n", cur, clr);
color[cur] = 0;
}
}
结果展示