zoukankan      html  css  js  c++  java
  • 【CF839E】Mother of Dragons 折半状压

    【CF839E】Mother of Dragons

    题意:给你一张n个点,m条边的无向图。你有k点能量,你可以把能量分配到任意一些点上,每个点分到的能量可以是一个非负实数。定义总能量为:对于所有边<a,b>,a的能量*b的能量 的和。让你最大化总能量。

    $nle 40,kle 1000$

    题解:容易发现,最后的分配方案一定是给一个大小为cnt的完全子图中的每个点都分配$kover cnt$点能量。

    那么本题就变成了一般图最大团问题,可以用随机化搞定,这里给出一种meet in the middle算法。

    对于前一半的点,用状压预处理出f[S]表示S中的最大团是什么。对于后一半的点,我们可以枚举其中的所有最大团,然后把与这些点都相邻的前一半的点拿出来,用前一半点的f值+后一半点的团大小更新答案即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    int n,m,n1,n2;
    double k;
    const int N=(1<<20)+4;
    ll v[50];
    int f1[N],Log[N],g[N],f2[N],cnt[N];
    int main()
    {
    	scanf("%d%lf",&n,&k);
    	int i,j,a;
    	for(i=0;i<n;i++)	for(j=0;j<n;j++)
    	{
    		scanf("%d",&a);
    		if(a)	v[i]|=1ll<<j,v[j]|=1ll<<i;
    	}
    	n1=n/2,n2=n-n/2;
    	for(i=0;i<n2;i++)	Log[1<<i]=i;
    	for(i=1;i<(1<<n1);i++)
    	{
    		a=Log[i&-i];
    		f1[i]=max(f1[i^(1<<a)],f1[i&v[a]]+1);
    	}
    	m=f1[(1<<n1)-1];
    	g[0]=1,f2[0]=(1<<n1)-1;
    	for(i=1;i<(1<<n2);i++)
    	{
    		a=Log[i&-i];
    		f2[i]=f2[i^(1<<a)]&v[a+n1],cnt[i]=cnt[i^(1<<a)]+1;
    		if(g[i^(1<<a)]&&(((v[a+n1]>>n1)&i)==(i^(1<<a))))	g[i]=1,m=max(m,f1[f2[i]]+cnt[i]);
    	}
    	printf("%.10f",k*k*(m-1.0)/m/2.0);
    	return 0;
    }
  • 相关阅读:
    SQL优化值-exists
    Oracle执行计划详细讲解
    SpringBoot配置加解密工具之Jasypt
    升级Spring Boot 2.0后RelaxedPropertyResolver不可用的解决方案
    Spring, SpringBoot之占位符源码解析
    springboot启动原理深度解析
    Java SPI技术深度解读
    [VCSA7]添加共享磁盘
    [VCSA7]MacOS部署VCSA7
    [Oracle]查看数据库磁盘空间
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8283333.html
Copyright © 2011-2022 走看看