題目:給定乙個圖的鄰接矩陣,求出該圖的所有最大團。(最大完全子圖)
1.自己思考的樸素演算法
(1)根據題意畫出解空間樹(只以以1結點開始為例,其餘以其他結點開始的同下述方法)(下圖中綠色結點為進入遞迴,紅色結點為不進入遞迴)
從圖中發現,一種想法是按深度遍歷解集。關鍵問題就是如何設定遞迴的出口和去重。
(2)演算法思路。
設定一最大團列表。其中的每乙個元素即是乙個最大團。並記錄最大團的長度。
設定乙個臨時最大團列表。
對每乙個結點深度優先搜尋(這裡以1為例)。
將1加入臨時最大團列表。
對與1相連的所有結點進行判斷,如果該結點和臨時最大團的所有結點都相連(鄰接矩陣的定義格式使得該結點在臨時最大團中的去重工作,在相連判斷中已經做完)
那麼對該點進行遞迴呼叫。這裡進入2結點的遞迴。
將2加入臨時最大團列表。
對2的所有相鏈結點進行判斷,1和1無相連邊(重複),3和1無相連邊,5和1有相連邊。這裡進入結點5的遞迴
將5加入臨時最大團列表。
對5的所有相鏈結點進行判斷,1和1無相連邊(重複),2和2無相連邊(重複),3和1無相連邊。
退出遞迴,返回最上層。開始進入結點4的遞迴........
由此我們可以找到所有完全子圖。下面討論設定遞迴的出口。即每次深度遍歷到最後時,把臨時最大團加入到最大團列表的時機。
演算法行進到某一結點時,如果在該結點不遞迴操作。那麼這就是遞迴結束的時候,但這並不意味著從某一結點開始的遞迴遍歷,已經到達最深處。
在此可以進行判斷,比較當前臨時最大團的長度和最大團列表的長度。
如果當前臨時最大團的長度大於最大團列表的長度,那麼意味著當前找到的完全子圖要比之前找到的完全子圖大。
則清空原先的最大圖列表,將新找到的臨時最大子圖加入,並重置臨時最大團長度。
如果當前臨時最大團的長度等於最大團列表的長度,那麼意味著當前找到的完全子圖應該被加入到最大團列表。
這時又出現了新的問題,即當前新找到的臨時完全最大團是否會和最大團列表中的某一團重複?為了解決去重問題,我將
最大團列表中的每乙個最大團和臨時最大團進行比較。比較的方法時,將兩者都先進行排序(元素位置可能不同不利於判斷),排序後順次比較對應元素,
如果臨時最大團的元素和最大團列表中的所有最大團的元素都不相同,則將該臨時最大團加入到最大團列表。
如果當前臨時最大團的長度小於最大團列表的長度,則說明遞迴沒有進行到最深處或該完全子圖不是最大完全子圖,不處理即可。
(3)演算法完整**
# include # includeusing
namespace
std;
void maxtuan(int eages[25], int n, int index, vector *templump);
void sort(vector *lump);
vector
int>>maxlumps;
int maxlength = 0
;int
main()
}for (int i = 0; i < n; i++)
for (int i = 0; i < maxlumps.size(); i++)
cout
<
}return0;
}/*名稱:最大團演算法
功能:從乙個結點開始,尋找其最大完全子圖
*/void maxtuan(int eages[25],int n,int index,vector *templump)
}if(inlump)
else
else
if (templump->size() ==maxlength)
}if (count != 3
)
else
}if(pushmark) }}
}}}/*
氣泡排序法
*/void sort(vector *lump) }}
}
最大團問題
include cstdio include queue include cstring define max 20 using namespace std int n 城市數量 int x max 解向量 struct node priority queuepq void enqueue int ...
最大團問題
最大團問題 首先介紹一些基本概念 1 什麼是團?如果乙個子圖是乙個無向圖的完全子圖,那麼可以稱為乙個團。2 什麼是極大團?如果乙個團不是任何乙個團的子集,那麼可以稱做乙個極大團。3 如果乙個極大團的大小是最大的,那麼可以被稱為乙個最大團。最大團有以下常見性質,這裡不加證明的直接給出結論。最大團點的數...
最大團,極大團
團 對於給定圖g v,e 其中,v 是圖g的頂點集,e是圖g的邊集。圖g的團就是乙個兩兩之間有邊的頂點集合。簡單地說,團是g的乙個完全子圖。如果乙個團不被其他任一團所包含,即它不是其他任一團的真子集,則稱該團為圖g的極大團 maximal clique 頂點最多的極大團,稱之為圖g的最大團 maxi...