0037算法笔记分支限界法最大团问题.docx

上传人:b****8 文档编号:9047255 上传时间:2023-02-02 格式:DOCX 页数:14 大小:43.62KB
下载 相关 举报
0037算法笔记分支限界法最大团问题.docx_第1页
第1页 / 共14页
0037算法笔记分支限界法最大团问题.docx_第2页
第2页 / 共14页
0037算法笔记分支限界法最大团问题.docx_第3页
第3页 / 共14页
0037算法笔记分支限界法最大团问题.docx_第4页
第4页 / 共14页
0037算法笔记分支限界法最大团问题.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

0037算法笔记分支限界法最大团问题.docx

《0037算法笔记分支限界法最大团问题.docx》由会员分享,可在线阅读,更多相关《0037算法笔记分支限界法最大团问题.docx(14页珍藏版)》请在冰豆网上搜索。

0037算法笔记分支限界法最大团问题.docx

0037算法笔记分支限界法最大团问题

问题描述

    给定无向图G=(V,E),其中V是非空集合,称为顶点集;E是V中元素构成的无序二元组的集合,称为边集,无向图中的边均是顶点的无序对,无序对常用圆括号“()”表示。

如果U∈V,且对任意两个顶点u,v∈U有(u,v)∈E,则称U是G的完全子图(完全图G就是指图G的每个顶点之间都有连边)。

G的完全子图U是G的团当且仅当U不包含在G的更大的完全子图中。

G的最大团是指G中所含顶点数最多的团。

   如果U∈V且对任意u,v∈U有(u,v)不属于E,则称U是G的空子图。

G的空子图U是G的独立集当且仅当U不包含在G的更大的空子图中。

G的最大独立集是G中所含顶点数最多的独立集。

   对于任一无向图G=(V,E),其补图G'=(V',E')定义为:

V'=V,且(u,v)∈E'当且仅当(u,v)∈E。

   如果U是G的完全子图,则它也是G'的空子图,反之亦然。

因此,G的团与G'的独立集之间存在一一对应的关系。

特殊地,U是G的最大团当且仅当U是G'的最大独立集。

   例:

如图所示,给定无向图G={V,E},其中V={1,2,3,4,5},E={(1,2),(1,4),(1,5),(2,3),(2,5),(3,5),(4,5)}。

根据最大团(MCP)定义,子集{1,2}是图G的一个大小为2的完全子图,但不是一个团,因为它包含于G的更大的完全子图{1,2,5}之中。

{1,2,5}是G的一个最大团。

{1,4,5}和{2,3,5}也是G的最大团。

右侧图是无向图G的补图G'。

根据最大独立集定义,{2,4}是G的一个空子图,同时也是G的一个最大独立集。

虽然{1,2}也是G'的空子图,但它不是G'的独立集,因为它包含在G'的空子图{1,2,5}中。

{1,2,5}是G'的最大独立集。

{1,4,5}和{2,3,5}也是G'的最大独立集。

   算法设计

    最大团问题的解空间树也是一棵子集树。

子集树的根结点是初始扩展结点,对于这个特殊的扩展结点,其cliqueSize的值为0。

 算法在扩展内部结点时,首先考察其左儿子结点。

在左儿子结点处,将顶点i加入到当前团中,并检查该顶点与当前团中其它顶点之间是否有边相连。

当顶点i与当前团中所有顶点之间都有边相连,则相应的左儿子结点是可行结点,将它加入到子集树中并插入活结点优先队列,否则就不是可行结点。

   接着继续考察当前扩展结点的右儿子结点。

当upperSize>bestn时,右子树中可能含有最优解,此时将右儿子结点加入到子集树中并插入到活结点优先队列中。

算法的while循环的终止条件是遇到子集树中的一个叶结点(即n+1层结点)成为当前扩展结点。

  对于子集树中的叶结点,有upperSize=cliqueSize。

此时活结点优先队列中剩余结点的upperSize值均不超过当前扩展结点的upperSize值,从而进一步搜索不可能得到更大的团,此时算法已找到一个最优解。

   算法具体实现如下:

   1、MaxHeap.h

[cpp] viewplain copy

1.template  

2.class MaxHeap  

3.{  

4.    public:

  

5.        MaxHeap(int MaxHeapSize = 10);  

6.        ~MaxHeap() {delete [] heap;}  

7.        int Size() const {return CurrentSize;}  

8.  

9.        T Max()   

10.        {          //查  

11.           if (CurrentSize == 0)  

12.           {  

13.                throw OutOfBounds();  

14.           }  

15.           return heap[1];  

16.        }  

17.  

18.        MaxHeap& Insert(const T& x); //增  

19.        MaxHeap& DeleteMax(T& x);   //删  

20.  

21.        void Initialize(T a[], int size, int ArraySize);  

22.  

23.    private:

  

24.        int CurrentSize, MaxSize;  

25.        T *heap;  // element array  

26.};  

27.  

28.template  

29.MaxHeap:

:

MaxHeap(int MaxHeapSize)  

30.{// Max heap constructor.  

31.    MaxSize = MaxHeapSize;  

32.    heap = new T[MaxSize+1];  

33.    CurrentSize = 0;  

34.}  

35.  

36.template  

37.MaxHeap& MaxHeap:

:

Insert(const T& x)  

38.{// Insert x into the max heap.  

39.    if (CurrentSize == MaxSize)  

40.    {  

41.        cout<<"no space!

"<

42.        return *this;   

43.    }  

44.  

45.    // 寻找新元素x的位置  

46.    // i——初始为新叶节点的位置,逐层向上,寻找最终位置  

47.    int i = ++CurrentSize;  

48.    while (i !

= 1 && x > heap[i/2])  

49.    {  

50.        // i不是根节点,且其值大于父节点的值,需要继续调整  

51.        heap[i] = heap[i/2]; // 父节点下降  

52.        i /= 2;              // 继续向上,搜寻正确位置  

53.    }  

54.  

55.   heap[i] = x;  

56.   return *this;  

57.}  

58.  

59.template  

60.MaxHeap& MaxHeap:

:

DeleteMax(T& x)  

61.{// Set x to max element and delete max element from heap.  

62.    // check if heap is empty  

63.    if (CurrentSize == 0)  

64.    {  

65.        cout<<"Empty heap!

"<

66.        return *this;   

67.    }  

68.  

69.    x = heap[1]; // 删除最大元素  

70.    // 重整堆  

71.    T y = heap[CurrentSize--]; // 取最后一个节点,从根开始重整  

72.  

73.    // find place for y starting at root  

74.    int i = 1,  // current node of heap  

75.       ci = 2; // child of i  

76.  

77.    while (ci <= CurrentSize)   

78.    {  

79.        // 使ci指向i的两个孩子中较大者  

80.        if (ci < CurrentSize && heap[ci] < heap[ci+1])  

81.        {  

82.            ci++;  

83.        }  

84.        // y的值大于等于孩子节点吗?

  

85.        if (y >= heap[ci])  

86.        {  

87.            break;   // 是,i就是y的正确位置,退出  

88.        }  

89.  

90.        // 否,需要继续向下,重整堆  

91.        heap[i] = heap[ci]; // 大于父节点的孩子节点上升  

92.        i = ci;             // 向下一层,继续搜索正确位置  

93.        ci *= 2;  

94.    }  

95.  

96.    heap[i] = y;  

97.    return *this;  

98.}  

99.  

100.template  

101.void MaxHeap:

:

Initialize(T a[], int size,int ArraySize)  

102.{// Initialize max heap to array a.  

103.    delete [] heap;  

104.    heap = a;  

105.    CurrentSize = size;  

106.    MaxSize = ArraySize;  

107.  

108.    // 从最后一个内部节点开始,一直到根,对每个子树进行堆重整  

109.   for (int i = CurrentSize/2; i >= 1; i--)  

110.   {  

111.        T y = heap[i]; // 子树根节点元素  

112.        // find place to put y  

113.        int c = 2*i; // parent of c is target  

114.                   // location for y  

115.        while (c <= CurrentSize)   

116.        {  

117.            // heap[c] should be larger sibling  

118.            if (c < CurrentSize && heap[c] < heap[c+1])  

119.            {  

120.                c++;  

121.            }  

122.            // can we put y in heap[c/2]?

  

123.            if (y >= heap[c])  

124.            {  

125.                break;  // yes  

126.            }  

127.  

128.            // no  

129.            heap[c/2] = heap[c]; // move child up  

130.            c *= 2; // move down a level  

131.        }  

132.        heap[c/2] = y;  

133.    }  

134.}  

   2、6d6.cpp

[cpp] viewplain copy

1.//最大团问题 优先队列分支限界法求解   

2.#include "stdafx.h"  

3.#include "MaxHeap.h"  

4.#include   

5.#include   

6.using namespace std;  

7.  

8.const int N = 5;//图G的顶点数  

9.ifstream fin("6d6.txt");     

10.  

11.class bbnode  

12.{  

13.    friend class Clique;  

14.    private:

  

15.        bbnode *parent;     //指向父节点的指针  

16.        bool LChild;        //左儿子节点标识  

17.};  

18.  

19.class CliqueNode  

20.{  

21.    friend class Clique;  

22.    public:

  

23.        operator int() const  

24.        {     

25.            return un;  

26.        }  

27.    private:

  

28.        int cn,         //当前团的顶点数  

29.            un,         //当前团最大顶点数的上界  

30.            level;      //节点在子集空间树中所处的层次  

31.        bbnode *ptr;    //指向活节点在子集树中相应节点的指针  

32.};  

33.  

34.class Clique  

35.{  

36.    friend int main(void);  

37.    public:

  

38.        int BBMaxClique(int []);  

39.    private:

  

40.        void AddLiveNode(MaxHeap&H,int cn,int un,int level,bbnode E[],bool ch);  

41.        int **a,        //图G的邻接矩阵  

42.            n;          //图G的顶点数  

43.};  

44.  

45.int main()  

46.{  

47.    int bestx[N+1];  

48.    int **a = new int *[N+1];    

49.    for(int i=1;i<=N;i++)      

50.    {      

51.        a[i] = new int[N+1];      

52.    }   

53.      

54.    cout<<"图G的邻接矩阵为:

"<

55.    for(int i=1; i<=N; i++)    

56.    {    

57.        for(int j=1; j<=N; j++)    

58.        {    

59.            fin>>a[i][j];        

60.            cout<

61.        }    

62.        cout<

63.    }  

64.  

65.    Clique c;  

66.    c.a = a;  

67.    c.n = N;  

68.  

69.    cout<<"图G的最大团顶点个数为:

"<

70.    cout<<"图G的最大团解向量为:

"<

71.    for(int i=1;i<=N;i++)      

72.    {     

73.        cout<

74.    }   

75.    cout<

76.  

77.    for(int i=1;i<=N;i++)      

78.    {     

79.        delete[] a[i];     

80.    }   

81.    delete []a;  

82.    return 0;  

83.}  

84.  

85.//将活节点加入到子集空间树中并插入到最大堆中  

86.void Clique:

:

AddLiveNode(MaxHeap &H, int cn, int un, int level, bbnode E[], bool ch)  

87.{  

88.    bbnode *b = new bbnode;  

89.    b->parent = E;  

90.    b->LChild = ch;  

91.  

92.    CliqueNode N;  

93.    N.cn = cn;  

94.    N.ptr = b;  

95.    N.un = un;  

96.    N.level = level;  

97.    H.Insert(N);  

98.}  

99.  

100.//解最大团问题的优先队列式分支限界法  

101.int Clique:

:

BBMaxClique(int bestx[])  

102.{  

103.    MaxHeap H(1000);  

104.  

105.    //初始化  

106.    bbnode *E = 0;  

107.    int i = 1,  

108.        cn = 0,  

109.        bestn = 0;  

110.  

111.    //搜集子集空间树  

112.    while(i!

=n+1)//非叶节点  

113.    {  

114.        //检查顶点i与当前团中其他顶点之间是否有边相连  

115.        bool OK = true;  

116.        bbnode *B = E;  

117.        for(int j=i-1; j>0; B=B->parent,j--)  

118.        {  

119.            if(B->LChild && a[i][j]==0)  

120.            {  

121.                OK = false;  

122.                break;  

123.            }  

124.        }  

125.  

126.        if(OK)//左儿子节点为可行结点  

127.        {  

128.            if(cn+1>bestn)  

129.            {  

130.                bestn = cn + 1;  

131.            }  

132.            AddLiveNode(H,cn+1,cn+n-i+1,i+1,E,true);  

133.        }  

134.  

135.        if(cn+n-i>=bestn)//右子树可能含有最优解  

136.        {  

137.            AddLiveNode(H,cn,cn+n-i,i+1,E,false);  

138.        }  

139.  

140.        //取下一扩展节点  

141.        CliqueNode N;  

142.        H.DeleteMax(N); //堆非空  

143.        E = N.ptr;  

144.        cn = N.cn;  

145.        i = N.level;  

146.    }  

147.  

148.    //构造当前最优解  

149.    for(int j=n; j>0; j--)  

150.    {  

151.        bestx[j] = E->LChild;  

152.        E = E->parent;  

153.    }  

154.  

155.    return bestn;  

156.}  

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1