hdu1530-回溯&最大团&菜鸟算法笔记-Maximum Clique

来源:互联网 发布:文明网络标语 编辑:程序博客网 时间:2024/06/04 19:39

http://acm.split.hdu.edu.cn/showproblem.php?pid=1530
给一个图,问你你求最大团的大小。
可什么是最大团呢,就是最大的最大完全子图。就是图中能包含的最大的完全图。
思路:搜索回溯,枚举每个点为起点人,然后回溯,就是一个点一个点的试。可是酱紫老是tle,后来拿剪刀剪了一下枝,还是不行,真是郁闷。
看了一下题解。。原来是要从小到大枚举,因为最大团,假设直接算,就有m!种方式,,这样计算量太大了。重复计算很多。一个方法就是标号从小到大。
注意:回溯有两种形式。一种是放在if里,用一个新变量传过去。这样对当前不影响,一种是手动放或者不放。
还有就是,用vis能节省一半时间。

#include<bits/stdc++.h>using namespace std;/* 回溯法解决最大a团问题。*/const int maxn=60;int g[maxn][maxn];int ans;int len;bool vis[maxn];int sum;void dfs(int m,vector<int>&v){     if(sum+(int)v.size()<ans) return;//能剪一点     ans=max((int)v.size(),ans);     for(int i=m+1;i<=len;i++){//这个是重点         if(g[m][i]){             bool flag=false;             for(int j=0;j<v.size()&&!flag;j++){                 if(!g[v[j]][i]) flag=true;             }              if(flag) continue;             vector<int>sss(v.begin(),v.end());             sss.push_back(i);             vis[i]=true;             sum--;             dfs(i,sss);             vis[i]=false;             //v.pop_back();             //vis[i]=false;             sum++;         }     }}int main(){    vector<int>q;    while(~scanf("%d",&len)){         if(!len) break;         q.clear();         memset(g,0,sizeof(g));         memset(vis,false,sizeof(vis));         for(int i=1;i<=len;i++){            for(int j=1;j<=len;j++){                scanf("%d",&g[i][j]);            }         }         ans=-1;         for(int i=1;i<=len;i++){           memset(vis,false,sizeof(vis));           vis[i]=true;           q.clear();           q.push_back(i);           sum=len-1;          dfs(i,q);          }          printf("%d\n",ans);       }    return 0;}

来个tle版本的。这种写法,一直t。。。可能是我太菜了。别人的卡过。

#include <bits/stdc++.h>using namespace std;/**/const int maxn=80;//int *vis;//int *res;bool vis[maxn];bool res[maxn];int siz;int ans;int m;int g[maxn][maxn];void dfs(int x){    if(x>=m){        ans=siz;        return;     }     bool flag=false;     for(int i=0;i<x&&!flag;i++){         if(vis[i]&&!g[i][x]){              flag=true;         }     }     if(!flag){          vis[x]=1;          siz++;          dfs(x+1);          siz--;     }       if(siz+m-x>ans)       {vis[x]=0;dfs(x+1);}    return ;}int main(){   while(~scanf("%d",&m)){         //vis=(int*)malloc(m+1*sizeof(int));         //res=(int*)malloc(m+1*sizeof(int));          if(!m)break;          memset(g,0,sizeof(g));          for(int i=0;i<m;i++){             for(int j=0;j<m;j++)             scanf("%d",&g[i][j]);         }         ans=0;        memset(vis,false,sizeof(vis));         siz=0;         dfs(0);         printf("%d\n",ans);         /*for(int i=0;i<m;i++){            if(res[i])                cout<<i<<endl;         }         cout<<endl;*/   }    return 0;}