【题目】http://acm.hdu.edu.cn/showproblem.php?pid=5952
【题意】给一个图,问里面点数等于s的完全图有多少个
【思路】从一个点开始搜索,将这个点加入a[]中,走到一个点,这个点能够到达a[]中的每一个点,那么就将这个点也加入a[]中,
递归直到a中的点数到达s个,ans++,将最后一个点删掉,回到上个点走另一条边继续递归;如果最后小于k个,那么将最后一个点删掉,走前一个点的另一条边继续递归。
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=105;
const int M=1005;
struct node
{
int v,nxt;
}edge[M];
int head[N],ei;
int n,m,s;
int a[N],ai;
int ans;
int mp[N][N];
void addedge(int u,int v)
{
edge[ei].v=v;
edge[ei].nxt=head[u];
head[u]=ei++;
}
void init()
{
memset(head,-1,sizeof(head));
ei=0;
}
void dfs()
{
if(ai==s)
{
ans++;
return;
}
int u=a[ai];
for(int i=head[u];i!=-1;i=edge[i].nxt)
{
int v=edge[i].v;
int flag=0;
for(int j=1;j<=ai;j++)
{
if(mp[v][a[j]]==0)
{
flag=1;
break;
}
}//只有当这个新来的点到前面已经进来的点都有边flag才能是0
if(flag==0)
{
a[++ai]=v;
dfs();
ai--;
}
}
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
init();
scanf("%d%d%d",&n,&m,&s);
memset(mp,0,sizeof(mp));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(u>v)swap(u,v);//只存小点到大点的边
addedge(u,v);
mp[u][v]=mp[v][u]=1;
}
ans=0;
for(int i=1;i<=n;i++)//因为只存了小点到大点的边,所以能保证从2搜时不会搜到1已经考虑过的情况。
{
ai=1;
a[1]=i;
dfs();
}
printf("%d\n",ans);
}
}