求图的最大团问题

搜索解空间:

1、约束条件:

只要第t个结点和前t-1个结点中被选中的结点都有边相连,则放入团中,否则不能放入

2、限界条件:

当第t个结点不能放入团中时,要判断假设下面的n-t个结点全放入团中加上当前以及放入的结点cn个的和:cn+n-t是否大于最优值bestn,若大于,则有必要继续搜索;

若小于等于,则没必要继续搜索,当前的bestn就是最优值,搜索可以结束了

3、搜索过程:从根节点出发,以深度优先搜索的方式进行,每次搜索一个结点,判断约束条件,满足则继续向其左分支向下继续搜索;如果不满足,则要判断限界条件,如果满足限界条件,则继续向其右子树向下继续搜索,不满足则当前bestn即是最优值,搜索结束。

 1 #include <iostream>
 2 #include <string.h> 
 3 using namespace std;
 4 const int N=100;
 5 int a[N][N];//图用邻接矩阵表示 
 6 bool x[N];//存储每个点是否加入团 
 7 bool bestx[N];//记录每个结点是否放入,记录最优解 
 8 int bestn;//记录最大值 
 9 int cn;//当前已放入团中的结点数量 
10 int n,m;//n为结点数,m为图中的边数
11 bool Place(int t){//判断第t个结点是否可以放入最大团 
12     bool ok=true;
13     for(int j=1;j<t;j++){
14         if(x[j]&&a[t][j]==0){//x[j]是第j个点放入了最大团中,a[t][j]是前面放入的t-1个结点是否和第t个点有相连边 
15             ok=false;
16             break;
17         }
18     }
19     return ok;
20 } 
21 void Backtrack(int t){
22     if(t>n){//到达叶结点 
23         bestn=cn;//将当前团个数设为最优值 
24         for(int i=1;i<=n;i++){//并寻找最优解:由哪些结点构成 
25             bestx[i]=x[i];
26         }
27         return ;
28     }
29     if(Place(t)){//满足约束条件,进入左子树 
30         cn++;//放入 
31         x[t]=1;//设为放入 
32         Backtrack(t+1);//进入下一层(左子树) 
33         cn--;//回溯回来cn-- ,怎么加的怎么减去 
34     }
35     if(cn+n-t>bestn){//满足限界条件,进入右子树 
36         x[t]=0;//不放入,cn不变 
37         Backtrack(t+1);//进入下一层(右子树) 
38     }
39 }
40 int main(){
41     int u,v;
42     cout<<"结点数n:";
43     cin>>n;
44     cout<<"边数m:";
45     cin>>m;
46     memset(a,0,sizeof(a));
47     cout<<"请输入有边相连的两点:";
48     for(int i=1;i<=m;i++){
49         cin>>u>>v;
50         a[u][v]=a[v][u]=1;
51     }
52     bestn=0;
53     cn=0;
54     Backtrack(1);
55     cout<<"最大团个数为:"<<bestn<<endl;
56     cout<<"分别为:";
57     for(int i=1;i<=n;i++)
58         if(bestx[i]==1)
59             cout<<i<<" ";
60     return 0;
61 } 

 

posted @ 2020-11-13 20:47  nilbook  阅读(185)  评论(0编辑  收藏  举报