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. Java进阶知识点:服务端高并发的基石 - NIO与Reactor AIO与Proactor

    一.背景 要提升服务器的并发处理能力,通常有两大方向的思路. 1.系统架构层面.比如负载均衡.多级缓存.单元化部署等等. 2.单节点优化层面.比如修复代码级别的性能Bug.JVM参数调优.IO优化等等 ...

  2. 清橙 A1318 加强版:Almost

    题意: 直接看题面吧 原版:\(n \leq 1e5, q \leq 3e4, TL 5s, ML 256G\) 加强版1:\(n,q \leq 1.5e5, TL 5s, ML 256G\) 加强版 ...

  3. Java程序员自我介绍

    有关Java程序员的面试自我介绍范文(一) 我叫XXX,今年21岁,毕业于XX解放军信息工程大学计算机科学与技术专业,拥有扎实的Core Java基础,良好的编程风格;熟悉JSP+Servlet+Ja ...

  4. HDU 2489 Minimal Ratio Tree(暴力+最小生成树)(2008 Asia Regional Beijing)

    Description For a tree, which nodes and edges are all weighted, the ratio of it is calculated accord ...

  5. 第八章 IO库

    8.1&&8.2 #include <iostream> #include <vector> #include <string> using nam ...

  6. 11.24Daily Scrum

    人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.990 测试 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.991 测试 王宇杰 负责后台代码测 ...

  7. Java之Math类使用小结(转发)

    Java的Math类封装了很多与数学有关的属性和方法,大致如下: public class Main { public static void main(String[] args) { // TOD ...

  8. java — 垃圾回收

    1. 垃圾回收的意义 在java中,当没有对象指向原先分配给某个对象的内存的时候,这片内存就变成了垃圾,JVM的一个系统级线程就会自动释放这个内存块,垃圾回收意味着程序不再需要的对象是“无用的信息”, ...

  9. 201621123034 《Java程序设计》第5周学习总结

    作业05-继承.多态.抽象类与接口 1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 答:关键字:接口.继承.多态 1.2 尝试使用思维导图将这些关键词组织起来.注:思维导图一般 ...

  10. c++:error2019,无法解析的外部命令blabla~

    出现这个原因的问题汇总: 1,相应的附加库没有包含进去,注意附加库的目录是 / 2,函数没有与之对应的类,却在main中以某一类的对象调用了该方法. 其实,当错误中显示fun()成为无法解析的外部命令 ...