最大團問題-分支界限法

最大團問題-分支界限法

  1. 遍歷所有點構造二叉樹;

  2. 廣度遍歷樹,遍歷過程中判斷當前結點的點數據時,是否構成完全子圖,如果不能則只將右結點加入隊列,每次選取隊列中完全子圖最大的結點作爲活結點,無子結點時到達葉子結點,記錄爲一個完全子圖,優先隊列法中第一個完全子圖即爲最優解。

package test;

import java.util.*;

/**
 * Created by saishangmingzhu on 2018/12/10.
 * 最大團問題
 */
public class MaximumCliqueProblem {

    //圖
    private int[][] pointIndex=new int[][]{
                                    {1,1,0,1,1},
                                    {1,1,1,0,1},
                                    {0,1,1,0,1},
                                    {1,0,0,1,1},
                                    {1,1,1,1,1}};

    public static void main(String[] arg){
        new MaximumCliqueProblem().branchAndBoundMethod();
    }

    /**
     * 分支界限法-優先隊列式
     * 優先隊列式求解時,到達第一個沒有子結點的活結點時,即爲最優解
     */
    public void branchAndBoundMethod() {
        List<Point> pointList=new ArrayList<>();
        pointList.add(new Point("1",0));
        pointList.add(new Point("2",1));
        pointList.add(new Point("3",2));
        pointList.add(new Point("4",3));
        pointList.add(new Point("5",4));
        //【1】構建樹
        Node root=new Node();
        createTree(pointList, root,0);
        //【2】廣度遍歷
        List<Node> currentLiveNodeList=new ArrayList<>();
        currentLiveNodeList.add(root);
        while (true) {
            //排序
            Node parent = currentLiveNodeList.get(0);
            if (parent.leftNode==null){
                //表示到了葉子結點,進行記錄
                //點不算子圖,所以要去除點集爲1的葉子
                break;
            }
            List<Point> leftPointList = parent.leftNode.hasPointList;
            if (judge(leftPointList) != 0) {
                currentLiveNodeList.add(parent.leftNode);
            }
            //因爲右結點是空,所以不需要判斷
            //List<Point> rightPointList=parent.rightNode.hasPointList;
            currentLiveNodeList.add(parent.rightNode);
            currentLiveNodeList.remove(parent);
            Collections.sort(currentLiveNodeList, new Comparator<Node>() {
                @Override
                public int compare(Node o1, Node o2) {
                    return o2.hasPointList.size()-o1.hasPointList.size();
                }
            });
        }
        System.out.println("最大團");
        for (Point point:currentLiveNodeList.get(0).hasPointList){
            System.out.print(point.name+",");
        }

    }

    /**
     * 判斷現有節點是否是完全子圖 -1 表示不是
     * @param pointList
     * @return
     */
    private int judge(List<Point> pointList){
        for (int i=0;i<pointList.size();i++){
            Point pointi=pointList.get(i);
            int indexi=pointi.index;
            for (int j=i+1;j<pointList.size();j++){
                Point pointj=pointList.get(j);
                int indexj=pointj.index;
                //使用[indexi][indexj]是爲了說明問題,可以直接使用[i][j]
                if (pointIndex[indexi][indexj]!=1){
                    return 0;
                }
            }
        }
        return 1;
    }

    private void createTree(List<Point> pointList, Node parent,int i) {
        if (i>=pointList.size()){
            return;
        }
        Node leftNode=new Node();
        leftNode.hasPointList.addAll(parent.hasPointList);
        leftNode.hasPointList.add(pointList.get(i));
        i++;
        createTree(pointList,leftNode,i);
        parent.leftNode=leftNode;
        Node rightNode=new Node();
        rightNode.hasPointList.addAll(parent.hasPointList);
        createTree(pointList,rightNode,i);
        parent.rightNode=rightNode;
    }

    class Point{
        private String name;
        private int index;

        public Point(String name,int index) {
            this.name = name;
            this.index = index;
        }
    }

    class Node{
        private Node leftNode;
        private Node rightNode;
        private List<Point> hasPointList=new ArrayList<>();

    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章