Codeforces Round #428 (Div. 2) E 推理+求最大团(中途相遇法)(状态压缩)(代码能力)

来源:互联网 发布:怎么做时间轴java 编辑:程序博客网 时间:2024/06/15 04:41

题目链接

题解:

Lemma : Let G be a simple graph. To every vertex of G we assign a nonnegative real number such that the sum of the numbers assigned to all vertices is 1. For any two connected vertices (by an edge), compute the product of the numbers associated to these vertices. The maximal value of the sum of these products is when assign equal numbers to a maximal clique (a subgraph that all of its vertices are connected to each other) and 0 to the rest of the graph.

Proof : If the graph is complete of order n then the problem reduces to finding the maximum of  knowing that x1 + x2 + … + xn = 1. This is easy, since . The last inequality is just the Cauchy-Schwarz inequality and we have equality when all variables are .

Unfortunately, the problem is much more difficult in other cases, but at least we have an idea of a possible answer: indeed, it is easy now to find a lower bound for the maximum: if H is the complete subgraph with maximal number of vertices k, then by assigning these vertices  and to all other vertices 0, we find that the desired maximum is at least . We still have to solve the difficult part: showing that the desired maximum is at most .

Let us proceed by induction on the number n of vertices of G. If n = 1 everything is clear, so assume the result true for all graphs with at most n−1 vertices and take a graph G with n vertices, numbered 1, 2, ... , n. Let A be the set of vectors with nonnegative coordinates and whose components add up to 1 and E the set of edges of G. Because the function  is continuous on the compact set A , it attains its maximum in a point (x1, x2, ... , xn). If at least one of the xi is zero, then f(G) = f(G1) where G1 is the graph obtained by erasing vertex i and all edges that are incident to this vertex. It suffices to apply the induction hypothesis to G1 (clearly, the maximal complete subgraph of G1 has at most as many vertices as the maximal complete subgraph of G). So, suppose that all xi are positive. We may assume that G is not complete, since this case has already been discussed. So, let us assume for example that vertices 1 and 2 are not connected. Choose any number 0 < a ≤ x1and assign to vertices 1, 2, ... , n of G the numbers x1a, x2 + a, x3, ... , xn. By maximality of f(G), we must have  , where C1 is the set of vertices that are adjacent to vertex 2 and not adjacent to vertex 1 (the definition of C2 being clear). By symmetry, we deduce that we must actually have  , which shows that f(x1, x2, ... , xn) = f(0, x1 + x2, x3, ... , xn). Hence we can apply the previous case and the Lemma is solved.

Now by the Lemma , we have to find the maximal clique and get the answer.(Let the maximal clique have m vertices, then the answer is ).

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.

代码如下:

#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
原创粉丝点击