回溯法经典例题(三):java解最大团问题MCP

最大团问题(Maximum Clique Problem,MCP)

通俗点讲就是在一个无向图中找出一个点数最多的完全子图

问题描述

在这里插入图片描述
找出该图的最大团

重温相关的图论概念

  • 完全子图
    给定无向图G=(V,E),其中V是顶点集,E是边集。G’=(V’,E’)如果顶点集V’∈V,E’∈E,且G’种任意两个点有边相连,则称G’是G的完全子图
    (用更简洁的语言来说就是,某个图的所有顶点是另一个图的顶点子集,该图的边是另一个图的边集,并且任意两个顶点之间都有边)


  • 即极大完全子图
    当且仅当G不包含在G‘更大的子图中

  • 最大团
    在G’的所有团中包含顶点数最多的团

定义解空间

由题目可知,图中所有顶点仅含有两个对立属性,即属于最大团和不属于最大团,因此其解空间是由顶点的是否进入最大团组成的

确定解空间结构

在定义解空间时即可看出和01背包问题、装载问题相像的解空间,是一棵完全二叉树,所以解空间结构即是子集树

剪枝函数

进入左子树时判断顶点是否与已入团顶点有边
进入右子树判断判断最多能够有多少顶点,是否能够产生更优解

代码实现

package MaximumCliqueProblem;
import java.util.*;  
  
public class MCP {  
    static int[] x; // 当前解  
  
    static int n; // 图G的顶点数  
  
    static int cn; // 当前顶点数  
  
    static int bestn; // 当前最大顶点数  
  
    static int[] bestx; // 当前最优解  
  
    static boolean[][] matrix; // 图G的邻接矩阵  
  
    /** 
     * @param m 
     *            是邻接矩阵 
     * @param v 
     *            out the best solution 最优解 
     * @return the best result 最优值 
     */  
    public static int maxClique(boolean[][] m, int[] v) {  
        matrix = m;    //邻接矩阵必然是正方形  
        n = matrix.length;  
        x = new int[n];   //当前解  
        cn = 0;  
        bestn = 0;  
        bestx = v;   //刚开始V是什么都没有  
  
        backtrack(0);  
        return bestn;  
    }  
  
    private static void backtrack(int i) {  
          
        //只有到达5才到这里。  
        if (i == n) {  
            // 到达叶结点  
            for (int j = 0; j < n; j++) {  
                bestx[j] = x[j]; 
            }  
            bestn = cn;  
        }  
  
        // 检查顶点 i 与当前团的连接  
        boolean connected = true;  
        for (int j = 0; j < i; j++) {  
            if (x[j] == 1 && !matrix[i][j]) {  
                // i 和 j 不相连  
                connected = false;  
                break;  
            }  
        }  
        if (connected) {  
            // 进入左子树  
            x[i] = 1;  
            cn++;   //当前进了几步  
            trackback(i + 1);  
            cn--;  
        }  
        if (cn + n - i > bestn) {    //剪枝函数,如果比最优解还大,继续才有意义   n是可能的最优解有n个,加上cn表示已经找到解的个数,i表示已经走了的步数,才可能有最优解  
            // 进入右子树  
            x[i] = 0;  
            trackback(i + 1);  
        }  
    }  
  
    private static void test() {  
        boolean[][] matrix = {  { false, true, false, true, true },  
                                { true, false, true, false, true },  
                                { false, true, false, false, true },  
                                { true, false, false, false, true },  
                                { true, true, true, true, false } };  
        int[] v = new int[matrix.length];  
        int bestn = maxClique(matrix, v);   //返回值计算最大团个数  
        System.out.println("最优解是: " + bestn);  
        System.out.println(Arrays.toString(bestx));  
    }  
  
    public static void main(String[] args) {  
        test();  
    }  
} 
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值