Maximum Clique

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4114    Accepted Submission(s): 2175

Problem Description
Given a graph G(V, E), a clique is a sub-graph g(v, e), so that for all vertex pairs v1, v2 in v, there exists an edge (v1, v2) in e. Maximum clique is the clique that has maximum number of vertex.
 
Input
Input contains multiple tests. For each test:

The first line has one integer n, the number of vertex. (1 < n <= 50)

The following n lines has n 0 or 1 each, indicating whether an edge exists between i (line number) and j (column number).

A test with n = 0 signals the end of input. This test should not be processed.

 
Output
One number for each test, the number of vertex in maximum clique.
 
Sample Input
5
0 1 1 0 1
1 0 1 1 1
1 1 0 1 1
0 1 1 0 1
1 1 1 1 0
0
 
Sample Output
4
 
Author
CHENG, Long
 
Source
 
题意:
求最大团;最大团:
参考:http://www.cnblogs.com/yefeng1627/archive/2013/03/31/2991592.html  
        http://www.cnblogs.com/zhj5chengfeng/p/3224092.html

一、定义

一个无向图 G=(V,E),V 是点集,E 是边集。取 V 的一个子集 U,若对于 U 中任意两个点 u 和 v,有边 (u,v)∈E,那么称 U 是 G 的一个完全子图。 U 是一个团当且仅当 U 不被包含在一个更大的完全子图中。

G的最大团指的是定点数最多的一个团。

二、常用做法

1、顺序贪婪启发式搜索算法

2、局部搜索启发式算法

3、智能搜索启发式算法

4、遗传算法

5、模拟退火算法

6、禁忌算法

7、神经网络算法

8、改进蚁群算法-AntMCP

看了所列出的算法,是不是有一种头皮发麻的感觉。反正我是这样的感觉...因为上面的东西我都不会...

如果你想看上面的东西,百度百科中有一些简略的介绍,我太弱,没看懂。

百度百科传送门:最大团问题

下面说说常用的一种搜索算法

当然,这种算法很不高效,所以当图中有 100 个点以上时,请慎用

先看看一个显而易见的 DFS :

    初始化:

      从一个点 u 开始,把这个点加入到一个集合中,设为 U。遍历一遍所有和他相连的点,把他们放入另一个集合 S1 中,接下来进行第一遍 DFS

    第一遍 DFS :

      从 S1 中选择一个点 u1,这个点肯定和集合 U 中的任何一个点相连。把集合 S1 中 u1 能访问到的点加入到集合 S2 中,并把 u1 加入到集合 U 中,进行第二遍 DFS

    第二遍 DFS :

      从 S2 中选择一个点 u2,这个点肯定和集合 U 中的任何一个点相连。把集合 S2 中 u2 能访问到的点加入到集合 S3 中,并把 u2 加入到集合 U 中,进行第三遍 DFS

    第三遍 DFS :

      从 S3 中选择一个点 u3,这个点肯定和集合 U 中的任何一个点相连。把集合 S3 中 u3 能访问到的点加入到集合 S4 中,并把 u3 加入到集合 U 中,进行第四遍 DFS

    ......

    最底层的 DFS :

      当某个 S 集合为空集的时候,DFS 结束,这时候我们就找到了一个完全子图,用这个完全子图更新我们的最大团。退出当前的 DFS,返回上层 DFS,接着找下一个完全子图,直到找完所有的完全子图

按照上面介绍的 DFS 方法,肯定能够得到一个最大团,因为该 DFS 把所有的完全子图都枚举了一遍。但是这样做的时间复杂度是不是太高了?

于是产生了下面的 DFS 过程,大致上和上面的 DFS 一样,只不过有一些地方不太一样了

首先,我们先得到后几个点组成的最大团到底是多大,(最开始的时候肯定是最后一个点单独构成一个最大团,点数为1)然后我们再 DFS:

    初始化:

      从一个点 u 开始,把这个点加入集合 U 中。将编号比它大的且和它相连的点加入集合 S1 中,为了方便,将集合 S1 中的点有序,让他们从小到大排列,进行第一遍 DFS

    第一遍 DFS :

      从 S1 中选择一个点 u1,遍历 S1 中,所有编号比 u1 大且和 u1 相连的点,其实也就是排在 u1 后面,并且和 u1 相连的点,将它们加入集合 S2 中。同理,让 S2 中的点也按照编号也从小到大排列。将 u1 加入集合 U 中,进行第二遍 DFS

    第二遍 DFS :

      从 S2 中选择一个点 u2,遍历 S2 中,所有排在 u2 后面且和 u2 相连的点,并把它们加入集合 S3 中,让 S3 中的点按照编号从小到大排列,将 u2 加入集合 U 中进行第三遍 DFS

    第三遍 DFS :

      从 S3 中选择一个点 u3,遍历 S3 中,所有排在 u3 后面且和 u3 相连的点,并把它们加入集合 S4 中,让 S4 中的点按照编号从小到大排列,将 u3 加入集合 U 中进行第四遍 DFS

    ......

    最底层的 DFS :

      当某个 S 集合为空时,DFS 过程结束,得到一个只用后面几个点构成的完全子图,并用它去更新只用后面几个点构成的最大团。退出当前 DFS,返回上层 DFS,接着找下一个完全子图,直到找完所有的完全子图

上面的 DFS 过程,如果不加任何剪枝的话,其实和第一个 DFS 是差不多的,但是既然我们都这样 DFS 了,能不能想一想怎么剪枝呢?

假设我们当前处于第 i 层 DFS,现在需要从 Si 中选择一个 ui,把在 Si 集合中排在 ui 后面的和 ui 相连的点加入集合 S(i+1) 中,把 ui 加到集合 U 中

可能大家稍作思考之后就想到了一个剪枝:

剪枝1:如果 U 集合中的点的数量+1(选择 ui 加入 U 集合中)+Si 中所有 ui 后面的点的数量 ≤ 当前最优值,不用再 DFS 了

还有什么剪枝呢?

注意到我们是从后往前选择 u 的,也就是说,我们在 DFS 初始化的时候,假设选择的是编号为 x 的点,那么我们肯定已经知道了用 [x+1, n] ,[x+2, n],[x+3, n] ...[n,n] 这些区间中的点能构成的最大团的数量是多大

剪枝2:如果 U 集合中的点的数量+1(理由同上)+[ui, n]这个区间中能构成的最大团的顶点数量 ≤ 当前最优值,不用再 DFS了

有这两个剪枝就够了吗?

不,我们还能想出一个剪枝来:

剪枝3:如果 DFS 到最底层,我们能够更新答案,不用再 DFS 了,结束整个 DFS 过程,也不再返回上一层继续 DFS 了

为什么?因为我们如果再继续往后 DFS 的话,点的编号变大了,可用的点变少了(可用的点在一开始 DFS 初始化的时候就确定了,随着不断的加深 DFS 的层数,可用的点在不断的减少)

有了上面三个剪枝,100 个点以内的图,我们也能非常快的出解了

可能有人会问,如果想知道最大团包含哪些节点该怎么办?

这还不简单?每次 DFS 都会加一个点进入 U 集合中,DFS 到最底层,更新最大团数量的时候,U 集合中的点一定是一个完全子图中的点集,用 U 集合更新最大团的点集就行了

三、常用结论

1、最大团点的数量=补图中最大独立集点的数量

2、二分图中,最大独立集点的数量+最小覆盖点的数量=整个图点的数量

3、二分图中,最小覆盖点的数量=最大匹配的数量

4、图的染色问题中,最少需要的颜色的数量=最大团点的数量

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,best;
int mp[][],num[];
bool dfs(int s[],int sum,int cnt)// sum: 与u相连的顶点数量 , cnt表示当前团的数量
{
if(sum==){// 当此团中最后一个点 没有 比起序号大 的顶点相连时
if(cnt>best){// 问题1:best为最大团中顶点的数量
best=cnt;
return ;
}
return ;
}
int t[];
for(int i=;i<sum;i++){// 枚举每一个与 u 相连的顶点 s[i]
if(cnt+(sum-i)<=best) return ;// 剪枝1, 若当前 顶点数量cnt 加上还能够增加的最大数量 仍小于 best则 退出并返回false
if(cnt+num[s[i]]<=best) return ;// 剪枝2, 若当前 顶点数量cnt 加上 包含s[i]的最大团顶点数 仍小于 best则 退出并返回false
int k=;
for(int j=i+;j<sum;j++){// 扫描 与u相连的顶点 中与 s[u]相连的顶点 并存储到 数组 t[]中,数量为k
if(mp[s[i]][s[j]]) t[k++]=s[j];
}
if(dfs(t,k,cnt+)) return ;
}
return ;
}
int Maxt()
{
if(n<=) return ;
int s[];
best=;
for(int i=n-;i>=;i--){
int k=;
for(int j=i+;j<n;j++){// 遍历 [i+1, n] 间顶点,
if(mp[i][j]) s[k++]=j;
}
dfs(s,k,);
num[i]=best;// 得出顶点 i, 出发构成最大团 中顶点数量
}
return best;
}
int main()
{
while(scanf("%d",&n)&&n){
for(int i=;i<n;i++)
for(int j=;j<n;j++)
scanf("%d",&mp[i][j]);
printf("%d\n",Maxt());
}
return ;
}

HDU1530 最大团 模板的更多相关文章

  1. hdu 1530 最大团模板

    说明摘自:pushing my way 的博文 最大团 通过该博主的代码,总算理解了最大团问题,但是他实现时的代码效率却不算太高.因此在最后献上我的模板.加了IO优化目前的排名是: 6 yejinru ...

  2. POJ 3692 幼儿园做游戏 最大团 模板题

    Kindergarten Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6191   Accepted: 3052 Desc ...

  3. hdu1530 最大团简单题目

    题意:       给你一个无向图,让你找到这个图里面的最大团是多少. 思路:       最大图案是NP问题,直接暴力搜索,如果当前的这个点可以加入当前最大团,那么就选择加入或者舍去,如果不能加入, ...

  4. hdu1530 求最大团

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1530 求最大团裸题. 模板:maxx即为所求的最大团的值. #include<iostream& ...

  5. HDU3585 最大团+二分

    maximum shortest distance Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  6. 【HDU1530】【ZOJ1492】Maximum Clique

    Position: http://poj.org/problem?id=3241 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCod ...

  7. HDU分类

    原地址:http://www.byywee.com/page/M0/S607/607452.html 总结了一下ACM STEPS的各章内容,趁便附上我的Steps题号(每人的不一样). 别的,此文首 ...

  8. [转] UIImage 图像-IOS开发 (实例)

    转自  http://justcoding.iteye.com/blog/1470931 一 UIImageView 简介 UIImageView是显示图片的控件,显示图片时,首先需要把图片加载到UI ...

  9. maximum shortest distance

    maximum shortest distance Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...

随机推荐

  1. 1053 Path of Equal Weight (30 分)(树的遍历)

    题目大意:给出树的结构和权值,找从根结点到叶子结点的路径上的权值相加之和等于给定目标数的路径,并且从大到小输出路径 #include<bits/stdc++.h> using namesp ...

  2. POJ 2631 Roads in the North(求树的直径,两次遍历 or 树DP)

    题目链接:http://poj.org/problem?id=2631 Description Building and maintaining roads among communities in ...

  3. 【转】Hbuilder MUI 页面刷新及页面传值问题

    文章来源:http://www.111cn.net/sys/CentOS/67213.htm 一.页面刷新问题 1.父页面A跳转到子页面B,B页面修改数据后再跳回A页面,刷新A页面数据 (1).父页面 ...

  4. 手机站测试工具(node服务器)

    最近在工作中遇到手机站测试的问题,于是就写了一个node服务外加一个第三方的转二维码功能,欢迎拍砖~ 项目地址:https://github.com/finderL/webserver

  5. Qt自定义标题栏

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt自定义标题栏     本文地址:http://techieliang.com/2017/1 ...

  6. thinkPHP框架单一入口文件解析

    一.index.php  (可参考ThinkPHP学习手册http://document.thinkphp.cn/manual_3_2.html#entrance_file) index.php单入口 ...

  7. C运行时库

    原文地址:http://blog.csdn.net/wqvbjhc/article/details/6612099 在开发window程序是经常会遇到编译好好的程序拿到另一台机器上面无法运行的情况,这 ...

  8. iOS-开发中的时间处理

    做App避免不了要和时间打交道,关于时间的处理,里面有不少门道,远不是一行API调用,获取当前系统时间这么简单.我们需要了解与时间相关的各种API之间的差别,再因场景而异去设计相应的机制. 时间的形式 ...

  9. 《转》vue-cli的webpack模板项目配置文件注释

    一.文件结构 本文主要分析开发(dev)和构建(build)两个过程涉及到的文件,故下面文件结构仅列出相应的内容. ├─build │ ├─build.js │ ├─check-versions.js ...

  10. hdu 1162 Eddy's picture (最小生成树)

    Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...