HDU 5952Counting Cliques(深搜好题)

Counting Cliques
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3843 Accepted Submission(s): 1380

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

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

Recommend
jiangzijing2015 | We have carefully selected several similar problems for you: 6408 6407 6406 6405 6404

[题目来源]http://acm.hdu.edu.cn/showproblem.php?pid=5952

题意:有n个人,有m种相互认识的关系,求共有多少种不同的方案,使得这s个人相互都认识;

题解:最早想到组合数,最多只有C【n】【s】种情况,再减去所有多算的部分,小数据貌似可行,但n的范围100,组合数一定炸,又因为保证每个人最多认识20人,而C【20】【9】刚好不炸,但不能直接暴搜,需要少些保存的状态,于是利用单调性,只用vector保存比当前大的人的边,优化后能过。用now数组来保存当前总数为size的人都相互认识,即深搜时维护起点,已经那些人入了圈(圈内人互相认识),圈的大小。

附AC代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<vector>
using namespace std;
const int maxn=110;
int n,m,s,u,v,size,mp[maxn][maxn],ans,t;
vector<int> g[maxn];
void dfs(int u,int now[],int size)
{
    if(size==s) 
    {
        ans++;
        return;
    }
    bool ok=1;
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        ok=1;
        for(int j=1;j<=size;j++)
        if(!mp[v][now[j]])
        {
            ok=0;
            break;
        }
        if(ok)
        {
            now[++size]=v;
            dfs(v,now,size);
            now[size--]=0;
        }
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        cin>>n>>m>>s;
        for(int i=1; i<=n; i++) g[i].clear();
        memset(mp,0,sizeof(mp));
        ans=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&u,&v);
            if(u>v) swap(u,v);
            g[u].push_back(v);
            mp[u][v]=mp[v][u]=1;
        }
        for(int i=1;i<=n;i++)
        {
            size=1;
            int now[maxn];
            now[1]=i;
            dfs(i,now,size);
        }
        printf("%d\n",ans);
    }
 } 

猜你喜欢

转载自blog.csdn.net/qq_42618295/article/details/81749191