hdu 5952Counting Cliques(暴搜)

本文介绍了一个计数特定大小完全子图的问题,并提供了一种适用于小规模数据集的解决方案。通过深度优先搜索(DFS)遍历图的所有可能组合来找出所有指定大小的完全子图(clique),并分享了代码实现细节。

题目链接

Counting Cliques

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


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
 



题解:

因为数据量比较小,直接爆搜就可以了,不过有一点要注意,爆搜时用一个数组记录在完全图里面的点,而且为了保证不重复,这些点按照递增排列,那么对于边u-v(u<v)此时图就只需要存u->v就行了,不然会T。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=100+10;
int g[maxn][maxn];
int head[maxn];
struct edge
{
    int from,to,next;
}e[maxn*20];   //
int tol=0;
void add(int u,int v)
{
    e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
}
void init()
{
    memset(head,0,sizeof(head));
    memset(g,0,sizeof(g));
    tol=0;
}
int ans;
int n,m,s;
void dfs(int u,int sz,int *tmp)
{
    if(sz==s)
    {
        ans++;
        return;
    }
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        //if(v<u) continue;
        bool flag=true;
        for(int j=1;j<=sz;j++)
        {
            if(!g[tmp[j]][v])
            {
                flag=false;
                break;
            }
        }
        if(flag)
        {
            tmp[sz+1]=v;
            dfs(v,sz+1,tmp);
        }
    }
    
}

int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d%d",&n,&m,&s);
        init();
        while(m--)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            g[a][b]=g[b][a]=1;
            if(a>b) swap(a,b);
            add(a,b);    //只保存每个点比他大的相邻点
            //add(b,a);
        }
        ans=0;
        for(int i=1;i<=n;i++)
        {
            int tmp[maxn];
            memset(tmp,0,sizeof(tmp));
            tmp[1]=i;
            dfs(i,1,tmp);
        }
        printf("%d\n",ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值