E - Counting Cliques HDU - 5952
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E - Counting Cliques HDU - 5952相关的知识,希望对你有一定的参考价值。
E - Counting Cliques HDU - 5952
题意:
给你n个点,m个边,还有一个s,问这个图中有多少个等于s的点集可以组成一个完全图
题解:
这题。。直接暴力搜索就行
分析复杂度的时候,应该考虑只有1000条边,所以我最多才枚举1000条边,100个点,再加上每次判断最多1e6的时间复杂度,再加一些剪枝,肯定不会超时的
如何避免搜索重复呢?我们规定起点标号小于终点标号,这样边就成为单向边,不会反过来跑,这样实现剪枝且避免重复计算
具体实现为:我依次枚举每个点在完全图内,然后从这个点开始出发跑,每到一个新点,判断他是否与已经存的所有点都有边,都有边说明他也在完全图中,加入,然后继续,直到满足s个点集,然后return,继续跑
详细看代码
代码:
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
typedef long long ll;
using namespace std;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
int n,m,s;
const int maxn=130;
vector<int>vec[maxn];
bool edge[maxn][maxn];
int tot=0;
int vis[maxn];
void dfs(int x){
if(x==s){
tot++;
return ;
}
int pre=vis[x];
for(int i=0;i<vec[pre].size();i++){
int f=1;
int v=vec[pre][i];
for(int j=1;j<=x;j++){//与之前已经加入连通图的点查看是否都有边
if(edge[v][vis[j]]==0){
f=0;
break;
}
}
if(f==1){
vis[x+1]=v;
dfs(x+1);
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
tot=0;
memset(edge,0,sizeof(edge));
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
edge[u][v]=1;
edge[v][u]=1;
if(u<v) vec[u].push_back(v);
else vec[v].push_back(u);
}
for(int i=1;i<=n;i++){
memset(vis,0,sizeof(vis));
vis[1]=i;
dfs(1);
}
printf("%d\\n",tot);
for(int i=1;i<=100;i++)vec[i].clear();
}
return 0;
}
以上是关于E - Counting Cliques HDU - 5952的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 5952 Counting Cliques(DFS)
HDU 5952 Counting Cliques(dfs)