您的位置:首页 > 其它

算法复习:最大团问题(回溯法和分支限界法)

2016-05-31 16:46 1461 查看
问题描述

给定无向图G=(V,E),V是顶点集,E是边集。如果U⊆V,且对任意u,v∈U有(u,v)∈E,u,v是两个顶点的符号,则称U是G的完全子图。G的完全子图U是G的一个团当且仅当U不包含在G的更大的完全子图中。

2、一个例子



–子集{1,2}是G的一个大小为2的完全子图,但不是一个团,因为它包含于G的更大的完全子图{1,2,5}中。{1,2,5}、{1,4,5}和{2,3,5}都是G的最大团。

A 回溯法:

·问题空间(input):

-G=(V,E)

·解空间(output):

-图G的顶点集V的子集选取问题,Xi∈{0,1}

-约束函数:团的定义

-目标函数:所含顶点数最多

·解空间树(所有可能解的结构):

-子集数(因为这是一个子集选取问题)

·搜索空间(最优解的求解过程):

-约束函数 顶点i到已选入的顶点集中每一个顶点都有边相连。

-限界函数 有足够多的可选择顶点使得算法有可能在右子树中找到更大的团。

下面是根据图构造出来的树(没有构造完,虚线的地方可以继续往下画,相应的下面的表也是):



cn是当前顶点数,bestn是当前最大顶点数

下面的表是搜索过程:



Xi分别代表五个点,值为0代表没有选入顶点集U,值为1代表已选入顶点集U。

3、算法部分代码

int **a         //图G的邻接矩阵
int n           //图G的顶点数
int *x          //当前解
int *bestx      //当前最优解
int cn          //当前顶点数
int bestn       //当前最大顶点数

void MaxClique(int i)
{
if (i > n)      //到达叶节点,更新最优值和最优解
{
for (int j = 1;j <= n;j++)
bestx[j] = x[j];
bestn = cn;
return;
//搜索扩展节点时,检查顶点i与当前团的连接
}
int OK = 1;
for (int j = 1;j < i;j++)//扫描当前团

9e91
if (x[j] && a[i][j] == 0)//i与当前团的顶点j不相连
{
OK = 0;
break;
}
if (OK)//顶点i与当前团的每个顶点均有连接,进入左子树
{
x[i] = 1;//状态更新
cn++;
MaxClique (i + 1);
x[i] = 0;//输出叶节点后,搜索右子树之前的状态恢复(即回溯指搜索右子树)
cn--;
}
if (cn + n - i > bestn)//进入右子树
{
x[i] = 0;
MaxClique(i + 1);
}
}


4、算法效率

解最大团问题的回溯算法所需的计算时间为O(n2n)

B 分支限界法

优先队列式分支限界法

还是上面那题,图片再复制到这里



·解空间和解空间树都没变

·剪枝

-左子树:从顶点i到已选入的顶点集中每一个顶点都有边,否则剪枝

-右子树:顶点数上界小于当前最优值(就是上面的bestn)时剪枝

顶点数上界=已确定的顶点数+未确定的顶点数的上界

·优先队列中节点的优先级

-顶点数上界

解空间树如下:



现在懂节点上那两数字相加啥意思了吧

树搜索的过程如下表:



所以,这已经很明白了,回溯法求解搜索树是深度优先,先一条道走到底,再回溯找其他的看是不是比得到的最优,而分支限界是广度优先,一层一层往下找,中间不断排除不符合的,找到最下面一层就得到了最优解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: