1. 程式人生 > 實用技巧 >求圖的最大團問題

求圖的最大團問題

搜尋解空間:

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 }