无向图的最大团/最大独立集 算法总结

目录

  1. 概述
  2. 普通DFS
  3. Bron-Kerbosch算法

概述

最大团其实就是最大完全子图的点集,同理极大团也就是极大完全子图的点集,点集内所有的点两两之间都有边相连。

定义 (维基百科):

在图论领域的一个无向图中,满足两两之间有边连接的顶点的集合,被称为该无向图的团。

最大独立集其实就是补图的最大团,因为和最大团相反,最大独立集合内的点两两之间都没有边相连。

定义(维基百科):

一个独立集(也称为稳定集)是一个图中一些两两不相邻的顶点的集合。

普通DFS

该方法很简单粗暴,就是一个个节点尝试。维护一个当前团,每个节点都有两种状态(在当前团中或不在当前团中),如果无法再往里加节点了的话,那么当前团就成为了一个极大团,这样找到所有的极大团并作出比较取舍即可得到最大团。但是这样的时间复杂度达到了O(2n2^n2n),所以我们需要做一个剪枝,就是判断还没有入团且没有被排除过的点如果全部加入当前团也没办法达到当前最大团的大小的时候就跳出,但是这样就不能保证找到所有的极大团了,只能保证能够得到最大团。

代码

HDU1530 AC确认,该题纯模板题输入是直接输入了邻接矩阵

#include <iostream>
#include <unordered_map>
#include <cstring>
#include <vector>
/*
* 潘骏同志瞎几把模拟的DFS求最大团
* 本板子剪过枝了但是还是过不了POJ 2989
*/
using namespace std;
bool maps[105][105];//邻接矩阵,判断有没有边相连是O(1)的比较方便
vector<int> best;//当前最大团
vector<int> now;//当前尝试插入的团
int ans;
int n;
void dfs(int pos){if(pos==n+1){//所有的点都过了一遍,没有可插入的点了if(now.size()>best.size()){best=now;ans=1;} else if(now.size()==best.size()){best=now;ans++;}return;}bool flag=true;for(int i=0;i<now.size();i++){int nxt=now[i];if(!maps[pos][nxt]){flag=false;//该点和当前团内的点冲突,不能插入break;}}if(now.size()+(n-pos)>=best.size()){//剪枝,如果剩下的点全都加入也不能使最大团增大就退出if(flag){now.push_back(pos);dfs(pos+1);//尝试该点插入状态now.pop_back();}dfs(pos+1);//尝试该点未插入状态}
}int main() {ios::sync_with_stdio(0);cin.tie(0);while(cin>>n && n!=0){now.clear();best.clear();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>maps[i][j];dfs(1);cout<<best.size()<<endl;}return 0;
}

Bron-Kerbosch 算法

该算法本质也是DFS。引入三个集合,all集合,some集合,none集合,其中some集合代表待检查且可能能加入团的节点,none集合代表已经检查过且我们认为不能加入团的节点,all则是检查过并且我们认为能加入最大团的节点,当some集合和none集合都为空的时候,all集合即为我们需要求的极大团。每次我们检查some集合里的一个节点,并把它加入all集合,那么可能加入待检查序列的就是它自己的邻接点(毕竟要保证团内所有点都有边相连),和some集合做一个交集,none集合同样和邻接点们作交集,以保证some和none里面的点和all里的点都有边相连。把当前检查点从all里拿出来以后就放入none里面,再从some集合的下一个开始检查。some集合为空的时候就没有可以加入all集合的点了,some集合为空且none集合不为空的时候就代表none集合里面的点放进all集合团会更大(之前检查过这种情况),所以一定要两个集合都为空才行。

这里还要介绍一种优化方法,因为不加这个优化可能连板子题都会TLE。如果我们要从some里选一个点pivot加入到all里的话,它的邻接点势必会因为和some作交集而留在some里待检查,在下一层DFS里势必会被检查,所以没有必要在检查pivot的这一层里再以它们为起点去检查,这会导致重复。选pivot的时候也可以以度数的大小选度数最大的点,这样能减少的检查次数也最多。

时间复杂度最差是O(3(n/3)3^(n/3)3(n/3)) 证明(英文论文我也没看完,就看了个结论)

代码

POJ 2989 AC确认,裸板题加了个大于1000判断,不加pivot TLE,用STL 188ms,数组 47ms,度数排序32 ms

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
/*
* 潘骏同志瞎几把模拟的Bron-Kerbosch算法
* 本板子已优化到最佳
*/
using namespace std;
int some[130][130];//别用STL了,这题里就能省一半还多的时间了
int all[130][130];//这里的数组如上所述
int none[130][130];
bool maps[130][130];//邻接矩阵,判断有没有边相连是O(1)的比较方便
int degrees[130];//记录各个节点的度数
int ans;
bool cmp(int a,int b){return degrees[a]>degrees[b];//根据度数排序,度数最大的可以作为pivot点
}
void BronKerbosch(int pos,int al,int so,int no){if(so==0 && no==0){ans++;//这里的all[pos]即为我们极大团,要求最大团只需要比较一下al大小即可。return;}int pivot;if(so!=0){pivot=some[pos][0];//排过序了,所以当前some集合的第一个元素是度数最大的点for(int i=0;i<al;i++)all[pos+1][i]=all[pos][i];//从本层出发的遍历all集合的前面元素都是和本层一样的}for(int i=0; i<so; i++){int nxt=some[pos][i];if(maps[pivot][nxt])continue;//pivot优化,pivot的邻接点不检查int nso=0,nno=0;//下一层some集合的大小,下一层none集合的大小all[pos+1][al]=nxt;//把当前调查点加入到下一层的all集合中for(int j=0; j<so; j++)if(maps[nxt][some[pos][j]] && some[pos][j]!=-1)//求和邻接点的交集some[pos+1][nso++]=some[pos][j];for(int j=0; j<no; j++)if(maps[nxt][none[pos][j]])//求和邻接点的交集none[pos+1][nno++]=none[pos][j];BronKerbosch(pos+1,al+1,nso,nno);if(ans>1000)return;some[pos][i]=-1;none[pos][no++]=nxt;//从some中移除已经调查过的点并移入none}
}
int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF){memset(some,0,sizeof some);memset(all,0,sizeof all);memset(none,0,sizeof none);memset(degrees,0,sizeof degrees);memset(maps,0,sizeof maps);int so=0;for(int i=1;i<=n;i++)some[0][so++]=i;//一开始some集合要包含所有节点for(int i=0;i<m;i++){int a,b;scanf("%d%d",&a,&b);degrees[a]++;degrees[b]++;maps[a][b]=true;maps[b][a]=true;}sort(some[0]+1,some[0]+n+1,cmp);ans=0;BronKerbosch(0,0,so,0);//一开始层数为0,all和none都为空if(ans>1000){printf("Too many maximal sets of friends.\n");}else{printf("%d\n",ans);}}return 0;
}

参考了以下文章,表示感谢:
维基百科Bron-Kerbosch算法
https://blog.csdn.net/yo_bc/article/details/77453478

无向图的最大团/最大独立集 算法总结相关推荐

  1. 无向图的最大团/最大独立集

    讲解的博客:https://blog.csdn.net/SparkFucker/article/details/83051133 还没写完的代码: #include<iostream> # ...

  2. Bron–Kerbosch算法求一般图最大团/最大独立集

    最大团: V中取K个顶点,两点间相互连接   最大独立集: V中取K个顶点,两点间不连接    最大团数量 = 补图中最大独立集数 关于 Bron-Kerbosch算法(原文) 基础形式是一个递归回溯 ...

  3. 图论 最大团,最大独立集

    经典的NP完全问题,只有暴力解,时间复杂度O(n2^n) 对于无向图来说 所谓最大团, 其实就是找一个最大完全子图,最大就是包含的点最多. 而最大独立集 == 补图的最大团 这里使用深度优先搜索实现, ...

  4. POJ 1966 Cable TV Network【无向图点连通度 最小割 E-K算法求最大流】

    题目描述: 给你一个无向图,问你最少删掉几个点,使这个图成不连通. 解题报告: 概念 (1)一个具有 N 个顶点的图,在去掉任意 k-1 个顶点后 (1<=K<=N) 所得的子图仍连通, ...

  5. 无向图的最小生成树(prim算法)

    引子: 假设整个无向图中的点记为A,最小生成树中的点记为T,其他点记为Q(也就是Q= A-T),T与Q相连的边记为B 算法构造过程: 1.初始化:首先将一个点(随意一个)加入最小生成树中 2.在所有Q ...

  6. python实现最大独立集算法_2018校招总结(外企,国内大公司,国内创业公司)...

    2018校招总结(外企,国内大公司,国内创业公司) 本篇是我参加2018实习和校招的求职经历,实习和校招面了不少公司,就总结了笔试面试中遇到的一些问题和思考. 实习offer有网易互娱,今日头条,Hu ...

  7. 最大团 matlab,无向图中最大团问题的求解(附上matlab代码)

    一.问题描述: 团就是最大完全图:最大团就是数目最多的最大子图:[1] 对于给定的无向图G(V,E).如果U在V集合内,且对任意的u,v在集合V内,且(u,v)属于集合E,则称U是G的完全子图:(u, ...

  8. 【每日算法】【图论】【最小边覆盖 最小路径覆盖 最小顶点覆盖 最大独立集 最大团】

    最小边覆盖 = 最大独立集 = |V| - 最大匹配数 这个是在原图是二分图上进行的 最小路径覆盖和最小边覆盖不同,不要求给的图是二分图,而是要求是N x N的有向图,不能有环,然后根据原图构造二分图 ...

  9. 无向图的最大独立集和最大团

    首先说说最大独立集和最大团的意义: 最大独立集:从无向图中的顶点中选出k个并且k个顶点之间互不相邻,最大的k就是最大独立集 最大团:从无向图的顶点集中选出k个并且k个顶点之间任意两点之间都相邻(完全图 ...

最新文章

  1. mysql实现心跳表_第29问:MySQL 的复制心跳说它不想跳了
  2. 解决PHP大文件上传问题
  3. 4后期盒子叫什么_Carlife转Carplay盒子科普
  4. Weblogic数据池测试出错
  5. java 组合对象_Java 中组合模型之对象结构模式的详解
  6. Excel里,vlookup函数各种应用-匹配多列、多条件匹配
  7. 陆奇最新分享:数字化进程加速,创新者如何把握机会?
  8. ttl是什么意思啊_解读:单反和微单的区别是什么?摄影新手应该如何选择?
  9. 对领域驱动设计的理解与实践
  10. 手写邮箱获取验证码注册登录功能
  11. mysql奢姿密码_mysql trim函数和oracle有区别吗
  12. 北京上海等昨天大规模断网 专家称与太阳无关
  13. android字体右对齐,Android TextView将文本右对齐和左对齐
  14. 江苏开票系统安全接入服务器地址,江苏省增值税发票查询平台网址.doc
  15. stc12串口收发计算机,stc12c5a60s2串口程序
  16. 32、Java高级特性——日期操作类、Date类、SimpleDateFormat类、Calendar类
  17. BlockingQueue 知识点参考链接
  18. ACM计算几何专项练习题目总结
  19. 【操作系统】一起了解操作系统咯 | 原码,反码,补码,你理解到位了吗?
  20. ZeroMQ 中文指南 第一章 ZeroMQ基础【转载】

热门文章

  1. 3星|《反本能》:案例有点意思,推理不够严谨
  2. CAD图案复制到Excel里面怎么去掉空白部分?如何在CAD中绘制常用的标高符号?
  3. JavaScript的本地存储和会话存储
  4. cad坐标归零lisp_CAD图怎么归零
  5. matlab中怎样求峭度,【转】Matlab常用函数~
  6. 2021年起重机司机(限桥式起重机)考试内容及起重机司机(限桥式起重机)最新解析
  7. 闭环系统的零极点图判定稳定性_自动控制原理课件第3章.ppt
  8. [ctf逆向001]:逆向工程体系化入门
  9. eplan和西门子plc的对接_Eplan成为西门子PLM解决方案合作伙伴:集成Eplan和Teamcenter系统...
  10. Fedora 14 安装 mplayer + kmplayer