最大团问题属于图论里的经典问题,典型的案例是找出朋友圈关系图中最大的圈子,即两两相识的最大圈子。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<>(); } }