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)

HDU5952 Counting Cliques(暴力)

HDU 5952 Counting Cliques(dfs)

HDU - 5952 Counting Cliques (dfs)

HDU5952Counting Cliques

HDU5952 Counting Cliques 暴搜优化