Java学习第35-36天

Java学习第35天:图的 m 着色问题

问题描述:

 给定无向连通图 G 和 m 种不同的颜色。用这些颜色为图 G 和各顶点着色,每个顶点着一种颜色。是否有一种着色法使得图 G 中每条边的两个顶点着不同的颜色。这个问题是图的 m 可着色判定问题。若一个图最少需要 m 种颜色才能使图中的每条边连接的两个顶点着不同的颜色,则称这个数 m 为该图的色数。求一个图的色数 m 的问题称为图的 m 可着色优化问题。

四色问题是m图着色问题的一个特例,根据四色原理,证明平面或球面上的任何地图的所有区域都至多可用四种、颜色来着色,并使任何两个有一段公共边界的相邻区域没有相同的颜色。这个问题可将平面图转换成对平面点的着色判定问题,将地图的每个区域变成一个结点,若两个区域相邻,则相应的结点用一条边连接起来。如将五个区域换成用点的方式表示,如下图:

 即用矩阵的表示如下:

 用回溯法解空间,先假设三种颜色和三个点,解空间如下:

 代码如下:

//图的m着色

    /** 
    * @Description: 着色
    * @Param: [paraNumColors]
    * @return: void
    */
    public void coloring(int paraNumColors) {
        //初始化
        int tpNumNodes = connectivityMatrix.getColumns();
        int[] tpColorScheme = new int[tpNumNodes];
        Arrays.fill(tpColorScheme, -1);

        coloring(paraNumColors, 0, tpColorScheme);
    }

    /**
     * @Description: 着色。输出所有可能的方式
     * @Param: [paraNumColors(颜色数量), paraCurNumNodes, paraCurColoring]
     * @return: void
     */
    private void coloring(int paraNumColors, int paraCurNumNodes, int[] paraCurColoring) {
        int tpNumNodes = connectivityMatrix.getColumns();

        System.out.println("coloring: paraNumColors = " + paraNumColors + ", paraCurrentNumNodes = "
                + paraCurNumNodes + ", paraCurrentColoring" + Arrays.toString(paraCurColoring));

        //说明已经完成了所有节点的颜色分配
        if (paraCurNumNodes >= tpNumNodes) {
            System.out.println("Find one:" + Arrays.toString(paraCurColoring));
            return;
        }

        //尝试所有可能的颜色
        for (int i = 0; i < paraNumColors; i++) {
            paraCurColoring[paraCurNumNodes] = i;
            if (!colorConflict(paraCurNumNodes + 1, paraCurColoring)) {
                coloring(paraNumColors, paraCurNumNodes + 1, paraCurColoring);
            }
        }
    }

    /**
     * @Description: 着色是否冲突。只将当前节点与相连接的节点比较
     * @Param: [paraCurNumNodes, paraCurColoring]
     * @return: boolean
     */
    private boolean colorConflict(int paraCurNumNodes, int[] paraCurColoring) {
        for (int i = 0; i < paraCurNumNodes - 1; i++) {
            //先判断当前节点与哪些节点相连接
            if (connectivityMatrix.getValue(paraCurNumNodes - 1, i) == 0) {
                continue;
            }

            //若连接,则判断它们的颜色是否相同
            if (paraCurColoring[paraCurNumNodes - 1] == paraCurColoring[i]) {
                return true;
            }
        }
        return false;
    }

/**
    * @Description: 着色测试
    * @Param: []
    * @return: void
    */
  public static void coloringTest() {
        int[][] tempMatrix = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 0 }, { 0, 1, 0, 0 } };
        Graph tempGraph = new Graph(tempMatrix);
        tempGraph.coloring(3);
    }

   public static void main(String args[]) {
		System.out.println("Hello!");
		Graph tempGraph = new Graph(3);
		System.out.println(tempGraph);

		// Unit test.
		getConnectivityTest();

		breadthFirstTraversalTest();

		depthFirstTraversalTest();

		coloringTest();
	}// Of main

运行结果:

coloring: paraNumColors = 3, paraCurrentNumNodes = 0, paraCurrentColoring[-1, -1, -1, -1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 1, paraCurrentColoring[0, -1, -1, -1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 2, paraCurrentColoring[0, 1, -1, -1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[0, 1, 1, -1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 1, 1, 0]
Find one:[0, 1, 1, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 1, 1, 2]
Find one:[0, 1, 1, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[0, 1, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 1, 2, 0]
Find one:[0, 1, 2, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 1, 2, 2]
Find one:[0, 1, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 2, paraCurrentColoring[0, 2, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[0, 2, 1, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 2, 1, 0]
Find one:[0, 2, 1, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 2, 1, 1]
Find one:[0, 2, 1, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[0, 2, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 2, 2, 0]
Find one:[0, 2, 2, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[0, 2, 2, 1]
Find one:[0, 2, 2, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 1, paraCurrentColoring[1, 2, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 2, paraCurrentColoring[1, 0, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[1, 0, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 0, 0, 1]
Find one:[1, 0, 0, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 0, 0, 2]
Find one:[1, 0, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[1, 0, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 0, 2, 1]
Find one:[1, 0, 2, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 0, 2, 2]
Find one:[1, 0, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 2, paraCurrentColoring[1, 2, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[1, 2, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 2, 0, 0]
Find one:[1, 2, 0, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 2, 0, 1]
Find one:[1, 2, 0, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[1, 2, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 2, 2, 0]
Find one:[1, 2, 2, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[1, 2, 2, 1]
Find one:[1, 2, 2, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 1, paraCurrentColoring[2, 2, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 2, paraCurrentColoring[2, 0, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[2, 0, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 0, 0, 1]
Find one:[2, 0, 0, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 0, 0, 2]
Find one:[2, 0, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[2, 0, 1, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 0, 1, 1]
Find one:[2, 0, 1, 1]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 0, 1, 2]
Find one:[2, 0, 1, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 2, paraCurrentColoring[2, 1, 2, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[2, 1, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 1, 0, 0]
Find one:[2, 1, 0, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 1, 0, 2]
Find one:[2, 1, 0, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 3, paraCurrentColoring[2, 1, 1, 2]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 1, 1, 0]
Find one:[2, 1, 1, 0]
coloring: paraNumColors = 3, paraCurrentNumNodes = 4, paraCurrentColoring[2, 1, 1, 2]
Find one:[2, 1, 1, 2]

Java学习第36天:邻连表

  1. 相当于图的压缩存储. 每一行数据用一个单链表存储.
  2. 重写了广度优先遍历和深度优先遍历. 可以发现, 使用队列的机制不变. 仅仅是把其中的 for 循环换成了 while, 避免检查不存在的边. 如果图很稀疏的话, 可以降低时间复杂度.
package day36;
import day13.LinkedList;
import day22.CircleObjectQueue;
import day25.ObjectStack;

public class NeighborList {
	class NeighborNode {
        //图序号
        int data;

        //下一节点
        NeighborNode next;


        public NeighborNode(int data) {
            this.data = data;
            next = null;
        }
    }

    //节点数量
    int numNodes;

    //每行的头节点
    NeighborNode[] headers;

    /**
     * @Description: 构造函数
     * @Param: [paraMatrix]
     * @return:
     */
    public NeighborList(int[][] paraMatrix) {
        numNodes = paraMatrix.length;

        NeighborNode tpNode;

        headers = new NeighborNode[numNodes];

        //链接上每个节点相邻接的节点
        for (int i = 0; i < numNodes; i++) {
            headers[i] = new NeighborNode(i);
            tpNode = headers[i];

            for (int j = 0; j < numNodes; j++) {
                if (paraMatrix[i][j] == 0) {
                    continue;
                }

                tpNode.next = new NeighborNode(j);
                tpNode = tpNode.next;
            }
        }
    }

    @Override
    public String toString() {
        String resString = "NeighborList: \n";

        NeighborNode tpNode;

        for (int i = 0; i < numNodes; i++) {
            tpNode = headers[i];


            while (tpNode.next != null) {
                resString += tpNode.data + "->";
                tpNode = tpNode.next;
            }

            resString += tpNode.data + "\n";
        }
        return resString;
    }

    /**
     * @Description: 广度优先遍历
     * @Param: [paraStartIndex]
     * @return: java.lang.String
     */
    public String breadthFirstTraversal(int paraStartIndex) {
        CircleObjectQueue tpQueue = new CircleObjectQueue();
        String resString = "";

        boolean[] tpVisitedArray = new boolean[numNodes];

        tpVisitedArray[paraStartIndex] = true;
        resString += paraStartIndex;
        tpQueue.enqueue(paraStartIndex);

        //根据节点去遍历
        int tpIndex;
        Integer tempInteger = (Integer) tpQueue.dequeue();
        NeighborNode tpNode;
        while (tempInteger != null) {
            tpIndex = tempInteger.intValue();

            tpNode = headers[tpIndex];

            while (tpNode.next != null) {
                tpNode = tpNode.next;
                if (tpVisitedArray[tpNode.data]) {
                    continue;
                }
                tpQueue.enqueue(tpNode.data);
                tpVisitedArray[tpNode.data] = true;
                resString += tpNode.data;
            }

            tempInteger = (Integer) tpQueue.dequeue();
        }
        return resString;
    }

    /**
     * @Description: 广度优先遍历测试
     * @Param: []
     * @return: void
     */
    public static void breadthFirstTraversalTest() {
        // Test an undirected graph.
        int[][] tempMatrix = {{0, 1, 1, 0}, {1, 0, 0, 1}, {1, 0, 0, 1}, {0, 1, 1, 0}};
        NeighborList tpNeighborList = new NeighborList(tempMatrix);
        System.out.println(tpNeighborList);

        String tempSequence = "";
        try {
            tempSequence = tpNeighborList.breadthFirstTraversal(2);
        } catch (Exception e) {
            System.out.println(e);
        }

        System.out.println("The breadth first order of visit: " + tempSequence);
    }


    /**
     * @Description: 深度优先遍历
     * @Param: [paraStartIndex]
     * @return: java.lang.String
     */
    public String depthFirstTraversal(int paraStartIndex) {
        ObjectStack tpStack = new ObjectStack();
        String resString = "";

        boolean[] tpVisitedArray = new boolean[numNodes];

        tpVisitedArray[paraStartIndex] = true;

        NeighborNode tpNode = headers[paraStartIndex];
        ;

        resString += paraStartIndex;

        tpStack.push(tpNode);

        int num = 1;
        while (num < numNodes) {

            while (tpNode.next != null && tpVisitedArray[tpNode.next.data]) {
                tpNode = tpNode.next;
            }

            //回溯
            if (tpNode.next == null) {
                tpNode = (NeighborNode) tpStack.pop();
                continue;
            }


            resString += tpNode.next.data;
            tpStack.push(tpNode.next);
            tpVisitedArray[tpNode.next.data] = true;
            tpNode = headers[tpNode.next.data];
            num++;
        }
        return resString;
    }

    /**
     * @Description: 深度优先遍历测试
     * @Param: []
     * @return: void
     */
    public static void depthFirstTraversalTest() {
        // Test an undirected graph.
        int[][] tempMatrix = {{0, 1, 1, 0}, {1, 0, 0, 1}, {1, 0, 0, 0}, {0, 1, 0, 0}};
        NeighborList tpNeighborList = new NeighborList(tempMatrix);
        System.out.println(tpNeighborList);

        String tempSequence = "";
        try {
            tempSequence = tpNeighborList.depthFirstTraversal(0);
        } catch (Exception ee) {
            System.out.println(ee);
        }

        System.out.println("The depth first order of visit: " + tempSequence);
    }
    public static void main(String[] args) {
        int[][] tempMatrix = {{0, 1, 0, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}, {0, 1, 1, 0}};
        NeighborList tpList = new NeighborList(tempMatrix);
        System.out.println(tpList);


        breadthFirstTraversalTest();

        depthFirstTraversalTest();
    }

}

测试有向图:

测试结果:

NeighborList: 
0->1
1->3
2->0
3->1->2

NeighborList: 
0->1->2
1->0->3
2->0->3
3->1->2

The breadth first order of visit: 2031
NeighborList: 
0->1->2
1->0->3
2->0
3->1

The depth first order of visit: 0132

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值