HDU-5952 Counting Cliques(16年ICPC沈阳赛区)(暴力DFS)

来源:互联网 发布:数据库unique 编辑:程序博客网 时间:2024/04/30 20:06

Counting Cliques

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


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
34 3 21 22 33 45 9 31 31 41 52 32 42 53 43 54 56 15 41 21 31 41 51 62 32 42 52 63 43 53 64 54 65 6
 

Sample Output
3715
 

Source

2016ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学) 

题意:给出一个无向图,要求求出点的个数恰好为s的完全子图的数目

题解:(万能的)暴力,具体原理看代码吧= =

#include<cstdio>#include<algorithm>#include<string.h>#include<bitset>using namespace std;const int maxn = 105;int s,ans;bool mp[maxn][maxn];/*这里的dfs看起来很简单,其实包含了一个很大的剪枝:在遍历某个点的时候,已经确定了已经加入团的点是与这个点相连的,还可以知道平均下来每个点的入度不会超过20,因此整个遍历的复杂度最高是C(9,20)*100*/void dfs(int mx,int v[],int cnt){    int nxt[maxn];    if(cnt==s) {ans++;return;}    for(int i=0;i<mx;i++){           //枚举能与点数为cnt的团构成点数为cnt+1的团的所有点        int len=0;        for(int j=i+1;j<mx;j++){            if(mp[v[i]][v[j]]){    //该团的所有"候选点"必须与已经选了的点相连                nxt[len++]=v[j];            }        }        dfs(len,nxt,cnt+1);    }}int main(){    int T,n,m,u,v;   // freopen("in.txt","r",stdin);    scanf("%d",&T);    while(T--){        scanf("%d%d%d",&n,&m,&s);        memset(mp,0,sizeof(mp));        for(int i=0;i<m;i++){            scanf("%d%d",&u,&v);            mp[u][v]=mp[v][u]=1;        }        ans=0;        int nxt[105];        for(int i=1;i<=n;i++){      //枚举每个点,这个点必须在所求的团里面,以这个点开始搜索            int len=0;            for(int j=i+1;j<=n;j++){                if(mp[i][j]){      //该团的所有"候选点"必须与已经选了的点相连                    nxt[len++]=j;                }            }            dfs(len,nxt,1);        }        printf("%d\n",ans);    }    return 0;}


0 0