ZOJ 1492 dfs剪枝求最大團

2021-07-27 22:31:26 字數 1303 閱讀 1650

要求乙個不超過50個點的圖中最大完全子圖(團)的大小。

dfs + 剪枝 + 記憶化

學習了這篇部落格的思路:

所謂團,就是乙個完全子圖,也就是在乙個圖中找到乙個子圖,滿足任意子圖中兩個點都有邊相連,最大團顧名思義就是點最多的團。

np-hard問題,沒什麼思路不妨考慮搜尋,按照團的定義,我們可以每次任意選擇乙個點開始當作乙個集合u,然後每次找到乙個點滿足和集合u中的所點都有邊相連,這樣的點就可以加入集合u,團的大小就增加了1。這是最基本的思路,就是列舉所有的完全子圖,為了避免列舉的重複,我們可以按照點來排序,每次從i個點之後搜尋更新集合u。

初始化的時候任意選擇乙個點u,然後將所有比u大且和u相連的點加入到集合st[1],然後進行第一層dfs,在st[1]中選擇乙個點v,將st[1]中比v大的且和v相連的點都加入集合st[2],再進行下一層dfs...最後終止的條件是這裡某一層的st[x]集合為空集,此時說明這個團無法再增大了,此時更新最大值。

當然僅僅是這樣的思路肯定會超時的,這時候我們需要記憶化+剪枝。用dp[i]儲存第i個點以後的點能得到的最大團的大小,免於重複計算。

有兩個很重要的剪枝:

剪枝1:如果 u 集合中的點的數量+1(選擇 ui 加入 u 集合中)+st[i] 中所有 ui 後面的點的數量 ≤ 當前最優值,就退出

剪枝2:如果 u 集合中的點的數量+1(理由同上)+[ui, n]這個區間中能構成的最大團的頂點數量 ≤ 當前最優值,就退出

#include #include #include #include using namespace std;

const int maxn = 105;

struct maxclique

void addedge(int u, int v, int w)

bool dfs(int sz, int num)

return false;

} for (int i = 0; i < sz; i++)

if (dfs(cnt, num + 1)) return true;

} return false;

} int solver()

dfs(cnt, 1);

dp[i] = ans;

} return ans;

}}maxclique;

int main()

} printf("%d\n", maxclique.solver());

} return 0;

}

歷屆試題 剪格仔 (DFS)

link 問題描述 如下圖所示,3 x 3 的格仔中填寫了一些整數。10 1 52 20 30 1 1 2 3 我們沿著圖中的星號線剪開,得到兩個部分,每個部分的數字和都是60。本題的要求就是請你程式設計判定 對給定的m x n 的格仔中的整數,是否可以分割為兩個部分,使得這兩個區域的數字和相等。如...

藍橋杯 剪格仔(dfs)

由題意可得從左上角的數開始dfs,途徑的數的和等於總和的一半時退出,注意走的時候可以斜著走,當總和為奇數時無法分割,當第乙個數即為總和一半時直接輸出1。include include include using namespace std const int m 15 int m,n,sum 0 i...

藍橋杯 剪格仔 DFS

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!問題描述 如下圖所示,3 x 3 的格仔中填寫了一些整數。10 1 52 20 30 1 1 2 3 我們沿著圖中的星號線剪開,得到兩個部分,每個部分的數字和都是60。本題的要求就是請你程式設計判定 對給定的m x n 的格仔中的整數,是否可以分割...