HDU5952 Counting Cliques计算完全图的个数 巧妙构图+dfs

题目传送门

      题目大意:给出n个点,m条无向边,让你计算这幅母图中有几个大小为s的完全图。

       完全图的意思是任意一个点都和其他点直接相连,完全图的大小指的就是完全图点的个数。

      思路:比较巧妙的构图方式。我们会很自然地想到用dfs来找环,然后记录路径,判断是否成完全图,但是由于题目给的是双向边,如果直接构图的话,就会导致出现很多没有必要的情况,重复计算,爆栈超时。

       所以在建图的时候只建从小的点到大的点的单向边,然后对n个点从小到大进行dfs,这样可以既可以保证不会有遗留的情况,也不会重复计算(因为每次走都是从小的点走到大的点,由于是单向边,所以不会回头)。dfs记录路径后,每次放入一个点,把之前路径上的所有点和这个点比较一下,是否是可达的,如果是,则继续dfs下一层,如果不是,则代表这个点无法和路径上的点一起构成完全图,舍弃,找下一条路。

      我存图的方式是链式前向星,这样可以减少遍历的次数,而判断完全图的方式是直接用邻接矩阵,节约时间。(也就是我存了两幅一样的图)。

 

      反思:还是一道赛后猛如虎的题目啊,比赛的时候想到用单向边构图,但是当时以为单向边判不了完全图(a能到b,我怎么知道b能不能到a),然后就没想下去了,实际上和答案只差一点点了呀!!

 

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
#include<sstream>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<bitset>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
inline int rd(void) {
	int x=0; int f=1;char s=getchar();
	while(s<'0'||s>'9') {	if(s=='-')f=-1;	s=getchar();}
	while(s>='0'&&s<='9') {	x=x*10+s-'0';s=getchar();}
	x*=f;return x;
}
int n,m,s,ans;
int head[1010],tot,lu[20];
struct edge{
	int v,Next;
}edge[1010];
int mp[110][110];
void init(){
	CLR(head,-1);
	tot=0;
	ans=0;
	CLR(mp,0);
}
void addv(int u,int v){
	edge[++tot].v=v;
	edge[tot].Next=head[u];
	head[u]=tot;
}
void dfs(int x,int deep){
	if(deep==s){
		ans++;
		return;
	}
	lu[deep]=x;
	for(int i=head[x];i!=-1;i=edge[i].Next){
		int flag=1;
		int v=edge[i].v;
		for(int j=1;j<deep;j++){
			if(mp[lu[j]][v]==0){
				flag=0;
				break;
			}
		}
		if(flag){
			dfs(v,deep+1);
		}
	}
	return ;
}
int main(){
	int T;
	cin>>T;
	while(T--){
		scanf("%d%d%d",&n,&m,&s);
		init();
		int a,b;
		for(int i=1;i<=m;i++){
			scanf("%d%d",&a,&b);
			if(a>b)swap(a,b);
			mp[a][b]=1;
			addv(a,b);
		}
		for(int i=1;i<=n;i++){
			dfs(i,1);
		}
		printf("%d\n",ans);
	}
}

Counting Cliques

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3880    Accepted Submission(s): 1387


 

Problem Description

A clique is a complete graph, in which there is an edge between every pair of the vertices. Given a graph with N vertices and M edges, your task is to count the number of cliques with a specific size S in the graph. 

 

 

Input

The first line is the number of test cases. For each test case, the first line contains 3 integers N,M and S (N ≤ 100,M ≤ 1000,2 ≤ S ≤ 10), each of the following M lines contains 2 integers u and v (1 ≤ u < v ≤ N), which means there is an edge between vertices u and v. It is guaranteed that the maximum degree of the vertices is no larger than 20.

 

 

Output

For each test case, output the number of cliques with size S in the graph.

 

 

Sample Input


 

3 4 3 2 1 2 2 3 3 4 5 9 3 1 3 1 4 1 5 2 3 2 4 2 5 3 4 3 5 4 5 6 15 4 1 2 1 3 1 4 1 5 1 6 2 3 2 4 2 5 2 6 3 4 3 5 3 6 4 5 4 6 5 6

 

 

Sample Output


 

3 7 15

posted @ 2018-08-24 20:41  光芒万丈小太阳  阅读(205)  评论(0编辑  收藏  举报