m-图着色问题(贪心解法)

problem

  1. 图的m色优化问题:给定无向连通图G,为图G的各顶点着色, 使图中任2邻接点着不同颜色,问最少需要几种颜色。所需的最少颜色的数目m称为该图的色数。
  2. 图的m色判定问题: 给定无向连通图G和m种颜色。用这些颜色为图G的各顶点着色.问是否存在着色方法,使得G中任2邻接点有不同颜色。

若图G是可平面图,则它的色数不超过4色(4色定理).
4色定理的应用:在一个平面或球面上的任何地图能够只用4种颜色来着色可使得相邻的国家在地图上着有不同颜色。

Solution

图的m色优化算法可用贪心法来解,其思想是:
任选一顶点着色1,在图中尽可能多的用颜色1着色;
当不能用颜色1着色时,转用颜色2将未着色的顶点尽可能多的着色···
直到所有顶点都被着色停止。

其伪代码如下:

1.for each vertex in G 初始化颜色为0
2.vertex[0]=1//选初始点颜色置为1
3.置颜色种类color=04.循环置所有顶点着色
    color++;//取下一颜色
    for each vertex in G
        if vertex[i]已着色,转下一顶点
        else
            若该点用color着色与其他邻接点颜色不冲突
            vertex[i]=color;
            否则不着色   

source code

边界条件:函数IsOk时,需要排除着色点和邻接点是同一点的情况。

#include <iostream>
using namespace std;

bool IsOk(int **map, int *vertex, int node, int color, int count)
{
    for (int i = 0; i < count; i++)
    {
        if (map[node][i] == 1 && vertex[i] == color && node != i)//邻接点且着色冲突,且冲突点不是该点本身
        return false;
        //if (map[node][i] == 1 && vertex[i] == color)也正确,因为判定点和着色点是同一点,着色点此时并未着色不会判false

    }
    return true;
}

int main(void)
{
    freopen("test.in", "r", stdin);
    freopen("result.out", "w", stdout);

    int count;
    cin >> count;
    int **map = new int *[count];//邻接矩阵
    int *vertex = new int[count];//存储顶点颜色
    //申请内存及初始化顶点颜色
    for (int i = 0; i < count; i++)
    {
        map[i] = new int[count];
        vertex[i] = 0;
    }

    //读邻接矩阵数据
    for (int i = 0; i < count; i++)
    for (int j = 0; j < count; j++)
        cin >> map[i][j];

    for (int i = 0; i < count; i++)
    {
        for (int j = 0; j < count; j++)
            cout << map[i][j]<< " ";
        cout << endl;
    }


    vertex[0] = 1;//置首节点颜色为1
    int color = 0;
    int flag = 1;//标志位,是否有节点未被染色

    while (flag)//每循环一次用颜色color给尽可能多的结点染色
    {
        color++;
        for (int i = 1; i < count; i++)
        {
            if (vertex[i] != 0)//已着色
                continue;
            else//未着色
            {
                if (IsOk(map, vertex, i, color, count))
                    vertex[i] = color;
            }
        }
        int k = 0;
        for (k = 1; k < count; k++)
        {
            if (vertex[k] == 0)//有顶点未被着色
                break;
        }

        if (k == count)
            flag = 0;
    }
    cout << "At less" << color << "colors are needed!" << endl;
    for (int i = 0; i < count; i++)
        cout << "Vertex " << i << ": " << vertex[i] << endl;


    return 0;
}

扩展

图着色问题可以用来解一系列带冲突对的划归问题,比如bad horse以及考场安排问题等问题。
考场安排:
设学校共有n门课,需要进行期末考试,因为不少学生不止选修一门课程,所以不能把同一个学生选修的两门课程安排在同一场次进行考试,问学期的期末考试最少需多少场次考完?(提示:如果两门课被同一个同学选上,则表示这两门课的顶点之间存在一条边)。

本问题可转换成是对m-图着色优化算法。将所选的每门课程变成一个结点,若一个同学选了m(1≤m≤n)门课程时,则这m门课程所对应的结点互相用一条边连接起来,及选了A,B,C,D四门课程,则每个课程都发出三条边与其他课程相连。则相邻边的顶点不能着同一种颜色,既不能安排在同一场次考试。本文所求即所有的顶点最少可用多少种颜色来着色。

    原文作者:贪心算法
    原文地址: https://blog.csdn.net/lime1991/article/details/47805881
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞