算法——四处碰壁回溯法02图解回溯

算法——四处碰壁回溯法02图解回溯

上一篇:算法——四处碰壁回溯法01入门案例

下一篇:算法——四处碰壁回溯法03组合回溯

一.图着色问题

问题描述:
给定无向连通图G=(V,E),求最小的整数m,用m种颜色是的对G中任意相连的顶点颜色不一致。

算法过程:
初始化定义数组color[n],其值全为0,同时将color[0]赋值1,表示节点涂上颜色1,设一个计数器k=1;表示已经有一个节点涂上颜色。
while(k<n)
①对color[k]开始颜色搜索,如果找到第一个没有颜色冲突的颜色(当然这个颜色值必然是小于m的)就为其赋值,进入②,否则进入③。
②k=k+1;处理下一个节点
③color[k]=0;k=k-1,进行回溯
循环结束返回true
算法复杂度分析:
用m种颜色来涂n节点的连通图,那么我们这里举一个例子,如图(m=3,n=5):

在这里插入图片描述
那么这个问题再回溯的过程中对应的是一个子集树。过程如下:在这里插入图片描述
上面的5,6是被抛弃的子集树的节点。最后使用的是1,2,4,7,14
代码实现:

import org.junit.Test;
/**
 * @author jackTan
 */
public class AlgrithimTest {
    @Test
    public void Test(){
        int edges[][] = {
                {0,1,1,0,0},
                {1,0,1,1,1},
                {1,1,0,0,1},
                {0,1,0,0,1},
                {0,1,1,1,0}
        };
        int[] ints = GraphColor(edges, 3);
        for (int anInt : ints) {
            System.out.print(anInt+" ");
        }
    }
    int[] GraphColor(int [][]edges,int m){
        int n = edges.length;
        int []color = new int[n];
        color[0]=1;
        int k=1;
        while(k<n){
            color[k]++;
            while(!IsOK(edges,color,k)){
                color[k]++;
            }
            if(color[k]<=m){
                k++;
            }else{
                color[k]=0;
                k--;
            }
        }
        return color;
    }
    /**
     *     用于判断相连的点是否同色
     */
    boolean IsOK(int [][]edges,int []color,int k){
        for(int i=0;i<k;i++){
            if(edges[k][i]==1&&color[k]==color[i]){
                return false;
            }
        }
        return true;
    }
}

输出:
在这里插入图片描述

二.哈密顿回路问题

这个问题也可以用动态规划来解决,可以参见这篇文章:
图问题中动态规划的应用

问题描述: 给定无向连通图G,邱一条从顶点0出发经过所有城市再回到0的哈密顿回路。

算法过程:

初始化数组visited[n];赋值全为0表示都未被访问过。利用x[n]来存储哈密顿回路的节点顺序,x[n]全为0。
从顶点0出发,那么visited[0]=1;x[0]=0;k=1(记录下一个要标记的顶点)
while(k<=n-1){
x[k]++;
{循环,若x[k]未被访问过且x[k-1]到x[k]有边且k<n就跳出,否则就x[k]++}
{若k==n则,k–,x[k]=0;
否则k++;}
}

下面代码演示的是下面这张图:
在这里插入图片描述
代码实现:

import org.junit.Test;
/**
 * @author jackTan
 */
public class AlgrithimTest {
    @Test
    public void Test(){
        int edges[][] = {
                {0,1,0,1,0},
                {1,0,1,0,1},
                {0,1,0,1,1},
                {1,0,1,0,1},
                {0,1,1,1,0}
        };
        int[] ints = Hamiton(edges);
        for (int anInt : ints) {
            System.out.print(anInt+1+" ");
        }
    }
    int[] Hamiton(int [][]edges){
        int n = edges.length;
        int []visited = new int[n];
        int []x = new int[n];
        visited[0]=1;
        x[0]=0;
        int k=1;
        while(k<=n-1){
            x[k]++;
            while(x[k]<=n-1&&!IsOK(edges,x,visited,k)){
              x[k]++;
            }
            if(x[k]==n){
                visited[x[k-1]]=0;
                x[k]=0;
                k--;
            }else{
                visited[x[k]]=1;
                k++;
            }
            if(k==n&&edges[x[k-1]][0]==0){
                visited[x[k-1]]=0;
                k--;
            }
        }
        return x;
    }
    boolean IsOK(int [][]edges,int x[],int []visited,int k){
        if(edges[x[k-1]][x[k]]==1&&visited[x[k]]==0){
            return  true;
        }else {
            return false;
        }
    }
}

在这里插入图片描述
上一篇:算法——四处碰壁回溯法01入门案例
下一篇:算法——四处碰壁回溯法03组合回溯

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值