POJ 2989

题意:给定一个无向图(节点数小于128)求极大团(不包含在更大的团中)的总数。

对最大团,极大团不熟悉的,建议先阅读最大团搜索问题 ZOJ 1492 再来看本题。

本题数据有限,可以使用dfs解决。类似于搜索最大团的加强版。有“两个”剪枝需要注意。

在dfs中需要维护两个集合即 Not(已经尝试过搜索极大团的节点)和Candidate(未曾尝试过的节点)由于极大团带有集合的性质,故某个节点在dfs序列中出现的位次并不重要。

当Not和Can集合同时为空时结束dfs。

在代码中,Not节点集合用ne数组标记,Can节点集合用ce数组标记

剪枝1:若当前Not集合中存在一个点,与Can中所有点都相连,则在未来的搜索中它永远不会离开Not集合,故剪枝。

剪枝2:这个剪枝为了优化剪枝1的效果,并不是一个新的剪枝。

    原本的搜索我们总是从Can集合中随意选择一个继续dfs 但是我们可以挑选一个特殊的节点,来增强剪枝1的效果。

设每个在Not集合中的节点有一个cnt值,为Can集合中与它不相连的节点个数。

我们于是选择Can集合中与cnt最小的节点不相连的节点进行下一步dfs。

代码如下

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std; const int maxn=130;
int n,m,ans,ne[maxn],ce[maxn],list[maxn][maxn];
bool g[maxn][maxn];
void dfs(int size)
{
if(ans>1000)return ;
int i,j,k,t,cnt,best=0;
if(ne[size]==ce[size])
{
if(ce[size]==0)++ans;
return ;
}
for(t=0,i=1;i<=ne[size];++i)
{
for(cnt=0,j=ne[size]+1;j<=ce[size];++j)
if(!g[list[size][i]][list[size][j]])++cnt;
if(t==0||cnt<best)t=i,best=cnt;
}
if(t&&best<=0)return ;//剪枝1
for(k=ne[size]+1;k<=ce[size];++k)
{
if(t>0)
{
for(i=k;i<=ce[size];++i)
if(!g[list[size][t]][list[size][i]])break;
swap(list[size][k],list[size][i]);//最大化剪枝1
}
i=list[size][k];
ne[size+1]=ce[size+1]=0;
for(j=1;j<k;++j)
if(g[i][list[size][j]])
list[size+1][++ne[size+1]]=list[size][j];
for(ce[size+1]=ne[size+1],j=k+1;j<=ce[size];++j)
if(g[i][list[size][j]])
list[size+1][++ce[size+1]]=list[size][j];
dfs(size+1);
if(ans>1000)return ;
++ne[size];
--best;
for(j=k+1,cnt=0;j<=ce[size];++j)
if(!g[i][list[size][j]])
++cnt;
if(t==0||cnt<best)t=k,best=cnt;
if(t&&best<=0)break;
}
} void cluster_count()
{
int i;
ne[0]=0;ce[0]=0;
for(i=1;i<=n;++i)
list[0][++ce[0]]=i;
ans=0;
dfs(0);
} int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(g,0,sizeof(g));
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
g[a][b]=g[b][a]=true;
}
cluster_count();
if(ans>1000)printf("Too many maximal sets of friends.\n");
else printf("%d\n",ans);
}
return 0;
}

  

最新文章

  1. 如何把Qlik Sense嵌入到Web应用中
  2. SQL SERVER几种数据迁移/导出导入的实践
  3. 域名dns查询_查询域名dns ip地址
  4. OllyDBG 1.10
  5. java进程性能分析步骤-超越昨天的自己系列(11)
  6. U3D assetbundle加载
  7. PostgreSQL中美元符号引用的字符串常量
  8. Apple-Watch开发
  9. RR模式下利用区间锁防止幻读,RC模式没有区间锁会出现幻读
  10. c#登录时保存账号密码到cookie
  11. PHP二维数组搜索返回数组
  12. unity 常用插件 2
  13. Centos-7修改yum源为国内的yum源
  14. Kylin, Mondrian, Saiku系统的整合
  15. vs2015 dx15开发教程一
  16. FB01与F-02的区别(转载)
  17. Activiti工作流的应用示例
  18. PAT 甲级 1132 Cut Integer
  19. 基于哈夫曼编码的压缩解压程序(C 语言)
  20. 浅析OC语言

热门文章

  1. Asp.Net集群中Session共享
  2. OpenSceneGraph几个重要功能节点练习
  3. 【T】并行调度
  4. 《R包的分类介绍》
  5. Angular - - ngCsp、ngFocus、ngBlur、ngForm
  6. C++第五天学习
  7. 滚轮事件的防冒泡、阻止默认行为的代码(效果是:只让当前div滚动,连当前文档都不滚动的效果)
  8. Servlet3.1规范和JSP2.3规范
  9. 转:Oracle弃用sun.reflect.Reflection.getCallerClass
  10. TypeScript教程2