用Welch Powell算法解决图着色问题(含C++代码)

Welch Powell 算法其实就是在进行贪心算法之前先对节点排了下序,具体过程如下:

(1) 将图 G 中的节点按度数的递减顺序进行排列(这种排列可能不是唯一的,因为有些节点的度数可能相同)

(2) 用第一种颜色对第一个节点着色,并按排列顺序对与前面着色节点不邻接的每一节点着上同样的颜色

(3) 用第二种颜色对尚未着色的节点重复步骤 (2),用第三种颜色继续这种做法,直到所有的节点全部着上色为止

具体实例网上有很多,我就不赘述了。

不过实现算法却很少,我主要参考了这篇博文里的代码,并做了一些修改。这篇博文里的代码逻辑是有点问题的,就是在节点排序前后有一些变量已经跟原先不对应了,所以需要相应地做些调整;但其代码结构还是很值得借鉴的,所以我继续沿用了这种风格。

#include 
#include 
#define MAX 100
using namespace std;

int c[MAX][MAX];
int n;

struct Vertex
{
    int color;
    int degree;
    int flag; // 标记原始点的位置
} vertex[MAX];

// 排序前的副本
Vertex copys[MAX];

// 初始化顶点颜色,并计算每个点的度数
void getDegree()
{
    for(int i = 1; i <= n; i++)
    {
        vertex[i].color = vertex[i].degree = 0;
        vertex[i].flag = i;
        for(int j = 1; j <= n; j++)
            vertex[i].degree += c[i][j];
    }
}

// 按顶点度数从大到小排序
bool cmp(Vertex a, Vertex b)
{
    return a.degree > b.degree;
}

int main()
{
    printf("输入顶点数:");
    scanf("%d", &n);
    printf("输入无向图的邻接矩阵:\n");
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            scanf("%d", &c[i][j]);
    getDegree();
    // 排序前保留一份副本
    for(int i = 1; i <= n; i++) {
        copys[i].color = 0;
        copys[i].degree = vertex[i].degree;
        copys[i].flag = vertex[i].flag;
    }
    sort(vertex + 1, vertex + n + 1, cmp);
    int coloredNum = 0;
    int k = 0;
    while(coloredNum < n)
    {
        k++;
        for(int i = 1; i <= n; i++)
        {
            // 如果没有着色
            if(vertex[i].color == 0)
            {
                bool ok = true;
                for(int j = 1; j <= n; j++)
                {
                    // 如果相邻顶点有相同颜色
                    if(c[vertex[i].flag][j] == 1 && copys[j].color == k)
                    {
                        ok = false;
                        break;
                    }
                }
                // 相邻顶点有相同颜色,直接跳过
                if(!ok)
                    continue;
                // 相邻顶点没有相同颜色,则对当前节点着色
                vertex[i].color = copys[vertex[i].flag].color = k;
                coloredNum++;
                printf("顶点 %d 着色为 %d\n", vertex[i].flag, vertex[i].color);
            }
        }
    }
    printf("共需 %d 种颜色\n", k);
}

例如,给此图着色(字母顺序对应数字顺序)
用Welch Powell算法解决图着色问题(含C++代码)_第1张图片
运行结果如下:
用Welch Powell算法解决图着色问题(含C++代码)_第2张图片

你可能感兴趣的:(图解法,c++)