题解:
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 x1−a, 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 long
using 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;
}