hdu1530-回溯&最大团&菜鸟算法笔记-Maximum Clique
2017-10-09 21:52
447 查看
http://acm.split.hdu.edu.cn/showproblem.php?pid=1530
给一个图,问你你求最大团的大小。
可什么是最大团呢,就是最大的最大完全子图。就是图中能包含的最大的完全图。
思路:搜索回溯,枚举每个点为起点人,然后回溯,就是一个点一个点的试。可是酱紫老是tle,后来拿剪刀剪了一下枝,还是不行,真是郁闷。
看了一下题解。。原来是要从小到大枚举,因为最大团,假设直接算,就有m!种方式,,这样计算量太大了。重复计算很多。一个方法就是标号从小到大。
注意:回溯有两种形式。一种是放在if里,用一个新变量传过去。这样对当前不影响,一种是手动放或者不放。
还有就是,用vis能节省一半时间。
来个tle版本的。这种写法,一直t。。。可能是我太菜了。别人的卡过。
给一个图,问你你求最大团的大小。
可什么是最大团呢,就是最大的最大完全子图。就是图中能包含的最大的完全图。
思路:搜索回溯,枚举每个点为起点人,然后回溯,就是一个点一个点的试。可是酱紫老是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; }
相关文章推荐
- HDU-1530 Maximum Clique 最大团裸题
- HDU 4513 吉哥系列故事——完美队形II(Manacher算法最大回文长度 && 两侧沿中点递减)
- hdu-1530-Maximum Clique-找最大团
- [HDU]1530 Maximum Clique 最大团问题[模板]
- hdu 1530 Maximum Clique(最大团模版)
- [HDU 1530] Maximum Clique 最大团
- HDU 1530 Maximum Clique 简单的最大团模板题
- 一个菜鸟的算法导论学习笔记【Introsuction&Chapter 1】
- hdu1530 Maximum Clique,最大团 , DP,邻接矩阵
- HDU 1530 Maximum Clique 图论最大团问题
- hdu 1530 Maximum Clique_最大团模板
- hdu 4862KM&最小费用最大流
- 【HDU 3376 Matrix Again】网络流 & 拆点 & 最大费用最大流
- 笔试算法题(26):顺时针打印矩阵 & 求数组中数对差的最大值
- hdu 1160 FatMouse's Speed(最大上升子序列dp)
- 一个菜鸟的算法导论学习笔记【Chapter 2】
- hdu 3729 I'm Telling the Truth(二分图最大匹配)
- HDU 2063 过山车 【匈牙利算法,二分图最大匹配】
- HDU 3068 Manacher 算法 求最大回文
- 算法笔记(堆实现的最大优先队列)