回溯,爆搜 刷题记录

算法只会暴力

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 }
    (*^▽^*)

     

posted @ 2019-10-28 14:45  连昵称都不能重复  阅读(107)  评论(0编辑  收藏  举报