最大团问题-回溯法

        最大团问题属于图论里的经典问题,典型的案例是找出朋友圈关系图中最大的圈子,即两两相识的最大圈子。java

        这里给出使用回溯法求解的两个方案:
node

        方案一:1.遍历全部点构造二叉树;ide

                    2.深度遍历树,遍历过程当中判断加入当前结点的点数据时,是否构成彻底子图,若是不能则走右结点,即剪枝左结点。达到叶子结点时即为一个彻底子图的解,进行记录;this

                    3.选择最大的记录做为最大团。(实现为以下代码)
get

        方案二:1.开始遍历点构造二叉树时就进行记录当前达到叶子的最大彻底子图,记录最大值为tmpMax,此值会在后续构造二叉树时更新;it

                    2.继续遍历点构造树的时候,计算当前结点所包含的彻底子图加剩余结点数是否大于以前记录的tmpMax,若是不大于,则直接剪枝,由于哪怕剩下全部结点都包含在彻底子图,也不会大于tmpMax。
class

package test;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by saishangmingzhu on 2018/12/9.
 * 最大团问题
 */
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}};
    private List<Node> leafNodeList=new ArrayList<>();

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

    /**
     * 回溯法
     */
    public void backtracking(){
        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】深度遍历+判断记录
        traversal(root);
        //【3】选最大
        System.out.println("全部子图");
        int size=0;
        Node maxNode=null;
        for (Node node:leafNodeList){
            if (size<node.hasPointList.size()){
                size=node.hasPointList.size();
                maxNode=node;
            }
            for (Point point:node.hasPointList){
                System.out.print(point.name+",");
            }
            System.out.println();
        }
        System.out.println("最大团");
        for (Point point:maxNode.hasPointList){
            System.out.print(point.name+",");
        }

    }

    private void traversal(Node parent){
        if (parent.leftNode==null){
            //表示到了叶子结点,进行记录
            //点不算子图,因此要去除点集为1的叶子
            if (parent.hasPointList.size()>1)
                leafNodeList.add(parent);
            return;
        }
        List<Point> leftPointList=parent.leftNode.hasPointList;
        if (judge(leftPointList)!=0){
            traversal(parent.leftNode);
        }
        //由于右结点是空,因此不须要判断
        //List<Point> rightPointList=parent.rightNode.hasPointList;
        traversal(parent.rightNode);
    }

    /**
     * 判断现有节点是不是彻底子图 -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<>();

    }
}
相关文章
相关标签/搜索