您的位置:首页 > 产品设计 > UI/UE

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

2017-10-09 21:52 447 查看
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++){

4000
if(res[i])
cout<<i<<endl;
}
cout<<endl;*/
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索