import java.io.*; import java.util.*; import java.lang.Math; /** * Class 'CliqueBT' finds the k-clique in a graph using backtracking method * @author Hyung-Joon Kim */ public class CliqueBT { private int [][] graph; // an adjacency edge matrix for a graph private static int numEdges; // total number of edges in a graph private static int sizeClique; // k = floor((1/2)*(log n)/log 2), n = |V| private static int numClique; // number of k-cliques in a graph private Vector firstClique; // a k-clique first found /** * Constructor: create a data structure of a graph. * @param numV total number of vertices in a graph. */ public CliqueBT(String numV) { int n = new Integer(numV).intValue(); graph = new int[n][n]; firstClique = new Vector(); sizeClique = (int)Math.floor(0.5*Math.log((double)n)/Math.log(2.0)); //sizeClique = 4; } /** * Add an edge to the adjacent edge matrix while reading pairs from the input. * For an undirected graph, only upper-right triangle in the matrix will be * filled with '1' if there is an edge. * @param v one vertex incident to the edge * @param x the other vertex incident to the edge */ public void addEdge(String v, String x) { int idxV1 = new Integer(v).intValue(); int idxV2 = new Integer(x).intValue(); graph[idxV1][idxV2] = 1; numEdges++; } /** * Check if there is an edge between vertex i and vertex j. */ public boolean isConnected(int i, int j) { return graph[i][j] == 1; } /** * Using recursive DFS, find k-cliques in a graph. Store only the first found * k-clique whereas it counts the number of all k-cliques in a graph. * @param A a vector to be tested if A is j-clique * @param j size of clique for each intermediate step in DFS */ public void doCliqueBT(Vector A, int j) { // If j is equal to size of clique, k, then A is k-clique in the graph if (j == sizeClique) { if (firstClique.isEmpty()) { firstClique = A; } numClique++; /////////////////////////////////////////////////////////////////// // The following is to display all k-cliques in a graph // - comment out this portion if the input graph is expected // to have a lot of such cliques. // System.out.print("Vertices in a clique: "); for (int i=0; i "); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String firstLine = br.readLine(); // 1st line contains only # of vertices StringTokenizer token = new StringTokenizer(firstLine); String numNodes = token.nextToken(); // Create an instance with given number of nodes in a graph CliqueBT cliqueBT = new CliqueBT(numNodes); // Read all edges in the form of pairs of vertices String pair = br.readLine(); token = new StringTokenizer(pair); while (token.hasMoreTokens()) { if (token.countTokens() == 0) { break; // no more input pair } else { String v = token.nextToken(); String x = token.nextToken(); cliqueBT.addEdge(v, x); // add edge to a graph if (!token.hasMoreTokens()) { // no more pair in this line pair = br.readLine(); // read a next line token = new StringTokenizer(pair); } } } // Stamp the starting time of the algorithm. long time1 = System.currentTimeMillis(); // Perform backtracking for clique with initially empty solution cliqueBT.doCliqueBT(new Vector(), 0); // Stamp the ending time of the algorithm. long time2 = System.currentTimeMillis(); // Determine running time of DFS long elapse = time2 - time1; System.out.println("\n Running Time of the algorithm : "+(long)elapse+" ms."); cliqueBT.showResult(); // show results of the backtracking for clique } }