HDU - 5952 Counting Cliques

Counting Cliques

HDU - 5952

OJ-ID:
hdu-5952

author:
Caution_X

date of submission:
20191110

tags:
dfs,graph

description modelling:
给定点数,边数,问包含有x个点的完全图种类数

major steps to solve it:
(1)选择一个点作为起点,记录该起点的所有连通点,dfs(该点)此时完全图有两个点
(2)遍历(1)中选定点的连通点,若构成完全图,则dfs(能够与(1)的图构成完全图的点)此时完全图有三个点 以此类推 当完全图点数=x时结束dfs
(3)重复(2)操作直到所有点都被作为起点使用过

warnings:
因为每一个起点都满足含有[2,x]个点的完全图,因此,不同起点达到x个点时的完全图相互独立

AC code:

#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;
}

猜你喜欢

转载自www.cnblogs.com/cautx/p/11874528.html