http://acm.split.hdu.edu.cn/showproblem.php?pid=5952
题目大意:
n个点 m条边的无向图 问节点个数为s的完全子图个数
分析:
一开始以为是规律题找了半天规律 发现重复的情况没法处理 自己太菜了处理不了 后来就想暴力 直接暴力是基本上不太可能了 最坏情况C(100,10)也是没法处理了 然后就想到按每个点暴力来找 判断与这个点相连的点是否可以加入完全图的集合中 可以就加入再从这个点开始向下找 结点个数为s时 ans++ 如果不能加入集合 就找与这个点相连的另一个点 存点时有向化一下去掉重复 节点小指向节点大的
AC代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include<list>
#include <bitset>
#include <climits>
#include <algorithm>
#define gcd(a,b) __gcd(a,b)
#define mset(a,n) memset(a,n,sizeof(a))
#define FIN freopen("input","r",stdin)
#define FOUT freopen("output","w",stdout)
typedef long long LL;
const LL mod=1e9+7;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
using namespace std;
int n,m,s;
int map0[105][105];// 存图
int tempans[105];// 完全图内点
int ans;// 最终结果
struct node{
int nn[105];// node内的点
int sizen;// 数组大小
}node[105];
void dfs(int k,int cnt){
if (cnt==s){
ans++;return;
}
for (int i=1;i<=node[k].sizen;i++){
int temp=node[k].nn[i-1];
int flag=0;
for(int j=1;j<=cnt;j++){
if (!map0[temp][tempans[j]]){
flag=1;
break;
}
}
if (!flag){
tempans[cnt+1]=temp;
dfs(temp,cnt+1);
tempans[cnt+1]=0;
}
}
}
int main (){
int t;
//FIN;
scanf ("%d",&t);
while (t--){
scanf ("%d%d%d",&n,&m,&s);
int u,v;
mset(node,0);mset(map0,0);
ans=0;
for (int i=0;i<m;i++){
scanf ("%d%d",&u,&v);
if (u>v) swap(u,v);// 有向化
node[u].nn[node[u].sizen++]=v;
map0[u][v]=map0[v][u]=1;
}
for (int i=1;i<=n;i++){
mset(tempans,0);
tempans[1]=i;
dfs(i,1);
}
printf ("%d\n",ans);
}
}