回溯,爆搜 刷题记录
算法只会暴力
HDU 5952 Counting Cliques
- 一个图,求大小为s的完全图的个数
- 每个完全图都给遍历一次。。。d(u,c,x)为遍历到大小为c的完全图(此时该完全图上的点都存在数组x里),然后u是此时该完全图上的点里最大的那个点
- 这样是为了每个完全图都只遍历一次,因为一定是按照编号从小到大遍历的
- 每次考察u的所有直连的点(只有这些点有可能和上面的图形成完全图),然后判断这个点是不是可以和上面的图形成完全图
- 时间复杂度就是所有大小为s的完全图的个数*20,其中可以优化的地方就是后面那个20了。。。但是我又懒又傻所以过了就行了。。。
- 代码:
1 #include <bits/stdc++.h> 2 #define nmax 110 3 4 using namespace std; 5 int cas,n,M,s,ans; 6 vector <int> g[nmax]; 7 int m[nmax][nmax]={0}; 8 9 inline void init(){ 10 memset(m,0,sizeof(m)); 11 for (int i=0; i<=n; i++) g[i].clear(); 12 ans=0; 13 } 14 15 inline void dfs(int u,int c,int* x){ //当前遍历了c个,其中最大的是u 16 if(c==s) { ans++; return; } 17 x[c]=u; 18 for (int i=0; i<g[u].size(); i++) { 19 int v=g[u][i]; 20 if(v<u) continue; 21 if(g[v].size()<c) continue; 22 bool flag=true; 23 for (int j=1; j<=c; j++) if(m[x[j]][v]==0) { flag=false; break; } 24 if(flag){ 25 x[c+1]=v; 26 dfs(v,c+1,x); 27 } 28 } 29 30 } 31 32 inline void add(int u,int v){ 33 g[u].push_back(v); 34 m[u][v]=1; 35 } 36 37 int main(){ 38 scanf("%d",&cas); 39 while(cas--){ 40 scanf("%d%d%d",&n,&M,&s); 41 init(); 42 int u,v; 43 for (int i=0; i<M; i++) { 44 scanf("%d%d",&u,&v); 45 add(u,v); 46 add(v,u); 47 } 48 for (int i=1; i<=n; i++) { 49 int p[nmax]; 50 p[1]=i; 51 dfs(i,1,p); 52 } 53 printf("%d\n",ans); 54 } 55 return 0; 56 }