最大团问题Word文档下载推荐.docx
- 文档编号:20324852
- 上传时间:2023-01-22
- 格式:DOCX
- 页数:6
- 大小:17.40KB
最大团问题Word文档下载推荐.docx
《最大团问题Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《最大团问题Word文档下载推荐.docx(6页珍藏版)》请在冰豆网上搜索。
这里提供ZJU1492的解答源代码加以具体说明(TLE2次,AC一次1.61s):
#include<
stdio.h>
string.h>
intjoint[50][50];
intSize;
intMAX;
intDP[50];
boolfind;
intreachEnd(intstart,intsets[])//返回-1表示邻接顶点集已经为空集,否则返回第一个公共顶点。
{
intlp;
for(lp=start;
lp<
Size;
lp++)
if(sets[lp])
returnlp;
return-1;
}
//Visit[]表示邻接数组,start表示搜索起点,切记只可向大的方向搜。
Depth表示搜索深度。
可以看到我们在函数中又定义了2
个和Visit【】一样内容的数组,这主要考虑到数组传递的指针,直接用Visit【】会直接改变joint邻接数组的内容,搜索之后状态无法还原。
而之所以是两个,因为SET要保存信息以便下次回溯。
Sets则是用来进行回溯时传递参数。
voidDFS(intVisit[],intstart,intdepth)
{
intloop;
intfirst;
intsets[50],SET[50];
memcpy(sets,Visit,Size*4);
memcpy(SET,Visit,Size*4);
if((first=reachEnd(start,sets))==-1)
if(depth>
MAX){
MAX=depth;
find=true;
}
return;
while(first!
=-1){
if(depth+Size-start<
=MAX)//不可能找到最有解
if(depth+DP[first]<
=MAX)//不可能找到最有解
return;
sets[first]=0;
SET[first]=0;
//从邻接顶点集中清除first顶点。
for(loop=first+1;
loop<
Size;
loop++)//合并邻接顶点集
if(SET[loop]==1&
&
joint[first][loop]==1)
sets[loop]=1;
else
sets[loop]=0;
DFS(sets,first,depth+1);
if(find)
//很巧妙的地方因为找到的只可能比原来的多一个结点,所以说,如果我找到了那就一定是当前最大的了
first=reachEnd(first,SET);
//更新接点
}
intmain()
intloop,lp;
intVisit[50];
while(scanf("
%d"
&
Size)!
=EOF&
Size!
=0)
for(loop=0;
loop++)
for(lp=0;
lp<
lp++)
scanf("
joint[loop]+lp);
MAX=0;
for(loop=Size-1;
loop>
=0;
loop--){
find=false;
memcpy(Visit,joint[loop],Size*4);
DFS(Visit,loop,1);
DP[loop]=MAX;
printf("
%d\n"
DP[0]);
return0;
图我们仍然用邻接数组表示。
最大的不同是DFS部分,可以看到,我们没有用普通的DFS一次就完成整个搜索的策略,而是对an,a(n-1),·
a2,a1分开调用DFS,这样方便我们记录每次搜索的结果。
看到DFS部分,reachEnd函数用来判定公共顶点集是否为空集,是空集,表明已经达到解状态树的叶接点,可以记录结果了。
Find表示此次搜索已经得到一个优化解,可以返回,结束这次的搜索了。
否则,继续搜索。
DFS部分的解释参见程序部分。
到这里,这道题就大部分解决了。
我们注意到这种算法的要点:
从小到大,小处的结论用来给更大范围的搜索提供强剪枝条件。
这和我们递归的至顶而下的做法可谓背道而驰。
这种算法将递归和小处规划紧密结合,让我们看到算法的精妙之处。
Ps:
我手中有PDF版的该算法的原版文章,有兴趣的给我发message。
ZJU1002和ZJU1654本质上属于这类问题,但是由于那种矩阵转化为邻接表比较麻烦,所以不推荐用该解法。
另外注
图G的最大独立集=G的补图(G'
)的最大团值
另外:
图G的最小顶点覆盖=顶点数(V)-G的补图(G'
所以,对于第四个内容,归根结底都是求最大团。
依样画葫芦呵呵
#include<
#defineN56
intmap[N][N];
intdp[N];
intvisit[N];
intMax=0;
intfinded;
intn;
intfind(intstart,intflag[])
inti;
for(i=start;
i<
n;
++i)
if(flag[i])
returni;
return-1;
voiddfs(intstart,intvisit[],intdepth)
intset[N];
intflag[N];
memcpy(set,visit,4*n);
memcpy(flag,visit,4*n);
intfirst;
first=find(start,flag);
if(first==-1)
{
if(depth>
Max)
Max=depth;
finded=1;
while(first!
=-1)
if(depth+n-start<
=Max)return;
if(depth+dp[first]<
set[first]=0;
flag[first]=0;
for(i=first+1;
if(flag[i]&
map[first][i])
set[i]=1;
elseset[i]=0;
dfs(first,set,depth+1);
if(finded)
first=find(first,flag);
while(scanf("
n),n)
inti,j;
for(i=0;
for(j=0;
j<
++j)
map[i][j]);
dp[i]=0;
Max=0;
for(i=n-1;
i>
=0;
--i)
finded=0;
memcpy(visit,map[i],4*n);
dfs(i,visit,1);
dp[i]=Max;
dp[0]);
return0;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 大团 问题