最大團問題屬於圖論裏的經典問題,典型的案例是找出朋友圈關係圖中最大的圈子,即兩兩相識的最大圈子。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<>(); } }