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个点时的彻底图相互独立
spa
AC code:.net
#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; }