编程语言
首页 > 编程语言> > 禁忌搜索算法实现图染色

禁忌搜索算法实现图染色

作者:互联网

1.图染色问题

给定一个无向图G = (V,E),其中V为顶点集合,E为边集合,要求将每个顶点进行着色,相邻顶点颜色不能相同,求如何着色使得所用 颜色数尽可能小。

2.算法流程

1.算法思路:由于无法直接找到比较少的颜色数,我们可以首先找到一个初始解,即找到可以染色成功的k种颜色,使相邻顶点颜色不相同,然后不断减小k值,直到该算法不能找到更小的k。

2.算法步骤:

(1)首先对于给定的无向图进行随机着色,然后计算每个顶点的k种颜色的冲突数(顶点的颜色与其它相邻顶点已着颜色相同的数量即为顶点颜色冲突数,用一个二维数组表示,p[1][A]即表示与顶点1相邻的顶点中着颜色A的顶点数量)

计算颜色冲突数代码:

for(int i=1;i<=vexnum;i++) {            //i表示顶点,t表示顶点i的颜色假设为颜色几,j表示与i相邻的顶点,初始化颜色冲突数
    for(int t=1;t<=k;t++) {
        for(int j=1;j<=vexnum;j++) {
            if(vex[j]==t&&edge[i][j]==1) {
                conflict++;
            }
        }
        p[i][t]=conflict;                   //顶点i颜色t的冲突数
        conflict=0;
    }
}

(2)接着判断是否存在将每个顶点现有颜色冲突数不为0的可以改为冲突数为0的颜色,如果存在就修改顶点,颜色直到所有顶点冲突数都为0表示k种颜色可以着色成功,这样我们接着使用k-1种颜色进行着色。

其中对于顶点颜色的修改我所使用的代码:

    void color_change(int f){            //修改相邻的顶点颜色冲突数
        int i=f;                        //顶点i的颜色可以修改
        for(int j=1;j<=vexnum;j++){
            if(edge[i][j]==1){          //co表示顶点新颜色
                p[j][co]++;             //相邻顶点的新颜色的冲突数加1
                p[j][vex[i]]--;         //相邻顶点的老颜色的冲突数减1
            }
        }
        vex[i]=co;
        it++;
   }

(3)当存在顶点颜色冲突数不为0且无法修改颜色使其为0时,我们采用禁忌搜索算法。禁忌搜索算法可以跳出局部最优,找到更优解(不一定找得到最优解),首先得设置一个禁忌表ta[vex][k],表示顶点vex的颜色k在一定迭代次数内被禁忌,即禁止顶点vex回到该颜色,故还得设置迭代次数的变量it,修改颜色数或者对冲突数进行一次判断就是一次迭代次数。当ta[vex][k]>it时表示被禁忌,否则就被解禁。通过此算法着色成功后记得初始化禁忌表ta。

    void tabu_search(){                        //这里的v,a只是随机的一个非禁忌点,通过它来找到一个顶点颜色冲突数最小的一个非禁忌点(当然不包括已经着色的顶点颜色)
        int best_count = 0;
        for(int i=1;i<=vexnum;i++) {
            for(int j=1;j<=k;j++) {
                if(vex[i]!=j&&p[v][a]>p[i][j]&&ta[i][j]<=it){
                    v=i;
                    a=j;
                    best_count = 1;
                }
                else if(vex[i]!=j&&p[v][a]==p[i][j]&&ta[i][j]<=it) {
                    best_count++;
                    int x=r.nextInt(best_count); //冲突数相同时是否选择的概率
                    if(x==0) {
                        v=i;
                        a=j;
                    }
                }
            }
        }
        ta[v][vex[v]]=it+r.nextInt(10)+30;       //禁忌次数为30-49的随机数
        for (int j = 1; j <=vexnum ; j++) {
            if(edge[v][j]==1){
                p[j][vex[v]]--;
                p[j][a]++;
            }
        }
        vex[v]=a;
        it++;
    }

(4)算法思考

我认为该算法需要考虑的是如何找一个禁忌长度以及如何选择禁忌点很重要,好的选择可以使k值变得更小。

标签:颜色,int,染色,禁忌,搜索算法,着色,冲突,顶点
来源: https://www.cnblogs.com/pr1012468597/p/14107213.html