51nod 1943 联通期望

105 篇文章 0 订阅
47 篇文章 0 订阅
该博客探讨了一种在建设桥梁时,考虑到海怪导致的不确定性,如何以期望最小成本使岛屿尽量联通的问题。博主介绍了利用克鲁斯卡尔算法的思想,并通过动态规划维护极大联通块的概率,实现复杂度为O(m * n^2)的解决方案。还提到了优化技巧,如卡精度处理和更高效的统计答案方法,但表示对于更优的O(2^n)解法感到困惑并寻求解答。
摘要由CSDN通过智能技术生成

在一片大海上有n个岛屿,规划建设 m m m座桥,第i座桥的成本为 z i zi zi,但由于海怪的存在,第i座桥有 p i pi pi的概率不能建造。
求在让岛屿尽量联通的情况下,期望最小成本为多少。
尽量联通:在对每座桥确定能否建造的情况下,对于任意两个岛屿,如果存在一种建桥方案使得它们联通,那么它们必须联通。
n &lt; = 14 , m &lt; = ( 2 n ) n&lt;=14,m&lt;=\binom 2n n<=14,m<=(n2)

模仿克鲁斯卡尔生成树过程 d p dp dp即可,
从小到大加入边,维护每个点集为极大联通块的概率,连边使点集合并时顺便计算答案即可。
复杂度:实现完美且苛刻的 O ( m 3 n − 2 ) O(m3^{n-2}) O(m3n2)
多一点都会T。。。
在这里插入图片描述

可以加入卡精度的优化(值小于eps就不算了)。
大概500ms。

AC Code:

#include<bits/stdc++.h>
#define maxn 14
using namespace std;

int n,m,lg[1<<14];
double p[14][14],f[1<<14],h[1<<14];
struct edge{
	int u,v,z;double p;
	bool operator <(const edge&B)const{ return z==B.z?u==B.u?v<B.v:u<B.u:z<B.z; }
}e[maxn*maxn];

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d%d%d%lf",&e[i].u,&e[i].v,&e[i].z,&e[i].p),e[i].u--,e[i].v--;
	sort(e+1,e+1+m);
	for(int i=2;i<(1<<n);i++) lg[i]=lg[i>>1]+1;
	for(int i=0;i<(1<<n);i++) h[i]=1;
	int now=1,pre=0;
	double ans = 0 , tmp;
	for(int i=0;i<n;i++) f[1<<i]=1;
	for(int i=1;i<=m;i++,swap(now,pre)){
		register int su=1<<e[i].u,sv=1<<e[i].v,suv=su|sv,sa=((1<<n)-1)^su^sv,rsa;
		for(int j=sa;;j=(j-1)&sa)if(f[j|su]){
			rsa = sa^j;
			for(int k=rsa;;k=(k-1)&rsa)if(f[k|sv]){
				f[suv|j|k] += (tmp = f[j|su]*f[k|sv]*(1-e[i].p)/(h[j|k|suv]/h[j|su]/h[k|sv]));
				ans += tmp*e[i].z;
 				if(!k) break;
			}
			if(!j) break;
		}
		for(int j=sa;;j=(j-1)&sa){
			f[su|j] *= e[i].p;
			f[sv|j] *= e[i].p;
			h[j|suv] *= e[i].p;
			if(!j) break;
		}
	}
	printf("%.6lf\n",ans);
} 

注意到计算答案时,可以不用子集合并,直接前i条边联通-前 i − 1 i-1 i1条边联通,可以做到统计答案 O ( 2 n ) O(2^n) O(2n)
大佬(讲题人)说联通概率可以,子集和卷积?然后 O ( 2 n ) O(2^n) O(2n),然后可以把 n n n开大,反正我。。。推不出来。急,离线等

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值