给定一张 个点的边集为 的无向图和一个正整数 ,你要给每个点分配一个非负实数点权 ,满足 且 最大。输出该式子的最大值(保留 位小数)。
,。
首先若 的点不组成完全图,则可以找到两个相互没有连边的点 ,不妨假设 ,那么把 全部给 肯定不劣。
并且根据数学直觉,点权肯定尽量平均分。
那么这就变成了最大团问题,这是个 NP 问题,但是我们有经典随机化算法:
随机一个加点顺序,若加入当前点后还是团则加入,否则不加入。
这个算法很难卡。
代码如下:
#include <iostream>
#include <cstdio>
#include <ctime>
#include <cstdlib>
using namespace std;
const int S=45,TS=1000000,RS=15;
int n,k;
int a[S][S];
int tot,b[S],c[S];
int main()
{
srand(time(NULL));
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) scanf("%d",&a[i][j]);
}
for(int i=1;i<=n;i++) b[i]=i;
int ans=0;
for(int tt=1;tt<=TS;tt++)
{
for(int i=1;i<=RS;i++) swap(b[rand()%n+1],b[rand()%n+1]);
int tot=0;
for(int i=1;i<=n;i++)
{
bool f=true;
for(int j=1;j<=tot&&f;j++) f&=a[b[i]][c[j]];
if(f) c[++tot]=b[i];
}
ans=max(ans,tot);
}
long double res=k*k/(long double)(ans*ans)*(ans*(ans-1)/2);
printf("%Lf\n",res);
return 0;
}