給定無向圖\(g = (v, e)\)。如果\(u \subseteq v\),且對任意\(u, v \in u\),有\((u, v) \in e\),則稱\(u\)是\(g\)的完全子圖。
完全子圖\(u\)是\(g\)的團\(\iff\)不包含在比\(g\)更大的完全子圖中。
\(g\)的最大團是指在\(g\)中所含頂點數最多的團。
設當前擴充套件節點\(z\)位於解空間樹的第\(i\)層。在進入左子樹前,必須確認從頂點\(i\)到已選入的頂點集中每個頂點都有邊相連。在進入右子樹前,必須確認還有足夠多的可選頂點,使得演算法有可能在右子樹中找到更大的團。
解空間:子集樹
可行性約束函式:\(x[j] == 1 \&\& !a[i][j]\),頂點\(i\)到已選入的頂點集中每乙個頂點都有邊相連
上界函式:\(cn + n - i > bestn\),即以選擇的結點數加上剩下的結點數需大於當前最優解的結點數
使用變數:
/**
* a 圖g的鄰接矩陣
* n 圖g的頂點數
* x 當前解
* bestx當前的最優解
* cn 當前頂點數
* bestn當前最大頂點數
**/int a[max + 1][max + 1] = ,,,
,,};int n = max;
int x[max + 1] = ;
int bestx[max + 1];
int cn;
int bestn;
核心**:
// i > n 表示找到當前的最優解,將路徑儲存到bestx陣列,將頂點數儲存到bestn
// 設定標誌變數ok,標識可行性約束函式的結果,ok = 1即表示當前節點可以加入到結果集中
// 對於通過約束函式的結點訪問其左子樹,並將當前結點新增到路徑中,並++結點數
// 再進行上界函式討論,即訪問結點右子樹,當右子樹中有足夠多的結點構成更大的團時,訪問右子樹
void backtrack(int i)
int ok = 1;
for (int j = 1; j < i; j++)
if (x[j] == 1 && a[i][j] == 0)
if (ok)
if (cn + n - i > bestn)
}
#include #include #define max 5
/** * a 圖g的鄰接矩陣
* n 圖g的頂點數
* x 當前解
* bestx當前的最優解
* cn 當前頂點數
* bestn當前最大頂點數
**/int a[max + 1][max + 1] = ,,,
,,};int n = max;
int x[max + 1] = ;
int bestx[max + 1];
int cn;
int bestn;
// i > n 表示找到當前的最優解,將路徑儲存到bestx陣列,將頂點數儲存到bestn
// 設定標誌變數ok,標識可行性約束函式的結果,ok = 1即表示當前節點可以加入到結果集中
// 對於通過約束函式的結點訪問其左子樹,並將當前結點新增到路徑中,並++結點數
// 再進行上界函式討論,即訪問結點右子樹,當右子樹中有足夠多的結點構成更大的團時,訪問右子樹
void backtrack(int i)
int ok = 1;
for (int j = 1; j < i; j++)
if (x[j] == 1 && a[i][j] == 0)
if (ok)
if (cn + n - i > bestn)
}void main()
最大團問題 回溯法
題目 對於給定的無向圖,找出他的最大團 分析 圖的乙個完全子圖就是乙個團,所以找最大團,通俗點講就是在乙個無向圖中找出乙個點數最多的完全圖 任意兩點之間均有邊相鄰 採用回溯法,對於解空間的子集樹,只有當前節點和所有已選的頂點都相連,才進入左子樹 而當 當前結點加上剩下節點數比最優節點的個數多時 才進...
回溯法 最大團問題c
本文參考 1 問題描述 給定無向圖g v,e v是頂點集,e是邊集。如果u v,且對任意u,v u有 u,v e,u,v是兩個頂點的符號,則稱u是g的完全子圖。g的完全子圖u是g的乙個團當且僅當u不包含在g的更大的完全子圖中。注 最大團定義 從無向圖的頂點集中選出k個並且k個頂點之間任意兩點之間都相...
演算法分析 回溯法 最大團問題
在若干點和若干連線中,找到完全子圖,即子圖中各個點都和其他點相連 有4部分 1.定義全域性變數 2.約束函式 限制生成左子樹的函式 3.遞迴函式 4.呼叫遞迴函式的函式,也可以直接寫在main 1.定義全域性變數 const int m1 5 元素數 vector vector a1 int cn1...