求一个图中的最大团(全连通分量) n = 40 (中途相遇法)

来源:互联网 发布:电脑连接不到网络 编辑:程序博客网 时间:2024/06/15 03:38

给出一个图,求图中的最大团,n = 40,应该怎么求呢?


我们可以使用中途相遇法,将原有的40个点分为两部分,每部分各20个点。在此之后,我们可以先对前20个点求出暴力求出所有团。设dp[mask]表示当前选择点的状态为mask(状态压缩)时的最大团数量。则在求整体最大团时,若得到后20个点中的当前团为p,找到在前二十个点中所有与p中所有点都有边的点集q,则maxc = max(maxc, dp[q] + p)。这样,我们就可以求出最大团的大小。

另见:http://blog.csdn.net/mosquito_zm/article/details/77170715

cf 题解版:We can find the maximal clique by the "meet in the middle" approach. Divide the vertices of the graph into 2 sets with equal number of vertices in each set(if n is odd, one set will have a vertex more than the other). We can save the maximal clique for each subset of the first set in dp[mask]. Now ,for each clique C in the second set, let v1, ... , vt be vertices in the first set that are connected to all of the vertices of C. Then m = max(m, dp[mask(v1, ... , vt)] + sizeof(C)) (m is size of maximum clique). Note : finding the maximal clique is also possible by a wise brute forces.

cf题目代码如下:

#include <bits/stdc++.h>#define ll long longusing namespace std;const int maxn = 40;const int C = 20;int dp[1 << C];ll adj[maxn];int n,m,k,x;int maxc(){for(int i = 0;i < n;i++){for(int j = 0;j < n;j++){scanf("%d",&x);adj[i] |= (ll)(i == j || x) << j;}}for(int i = 1;i < (1 << max(0,n - C));i++){int x = i;for(int j = 0;j < C;j++)if((i >> j) & 1)x &= adj[j + C] >> C;if(x == i) dp[i] = __builtin_popcount(i);}for(int i = 1;i < (1 << max(0,n - C));i++)for(int j = 0;j < C;j++)if((i >> j) & 1)dp[i] = max(dp[i], dp[i ^ (1 << j)]);int ans = 0;for(int i = 0;i < (1 << min(C,n));i++){int x = i,y = (1 << max(0, n - C)) - 1;for(int j = 0;j < min(C,n);j++)if((i >> j) & 1) x &= adj[j] & ((1 << C) - 1),y &= adj[j] >> C;if(x != i) continue;ans = max(ans, __builtin_popcount(i) + dp[y]);}return ans;}int main(){scanf("%d",&n);scanf("%d",&k);int tmp = maxc();long double x = (long double) k / tmp;ll ans = tmp * (tmp - 1) / 2;cout << fixed << setprecision(8) << x * x * ans << '\n';return 0;}


阅读全文
0 0
原创粉丝点击