题解

前置芝士:深度理解的矩阵树定理

矩阵树定理能求生成树个数的原因是,它本质上求的是:

\[\sum_T \prod_{e\in T} w_e
\]

其中 \(w_e\) 是边权,那么我们会发现其实当边权是 \(1\) 时,本式所求即为生成树个数。

那么回到这题来,这题让求的是

\[\sum_{T}\prod_{e\in T}w_e\prod_{e\notin T}(1-w_e)
\]

很容易看出来,这个式子和上面矩阵树的式子很像。让我们来推一波。

\[(\sum_T \prod_{e\in T} w_e) × \prod_{e}w_e=\sum_T\prod_{e\in T}w_e(1-w_e)\prod_{e\notin T}(1-w_e)
\]

此式和上面答案更近了一步,我们只需把 \(\prod_{e\in T}(1-w_e)\) 消掉即可。

显然

\[w_e=(1-w_e)×\frac{w_e}{1-w_e}
\]

所以,我们要求的就是 \(\sum_{T}\prod_{e\in T}\frac{w_e}{1-w_e}\) 

于是我们在初始化 \(Laplace\) 矩阵时直接以 \(\frac{w_e}{1-w_e}\) 为边权。

有一个需要注意的地方,因为 \(w_e\in [0,1]\),而 \(w_e\) 为分子,当 \(w_e=0\) 是,原式趋于无穷小,所以我们可以将其赋为 \(eps\) ,在分母上的 \(1-w_e\) 则反过来,若 \(w_e=1\) 则原式趋于无穷大,所以可以赋其为 \(1-eps\) 。

至于为什么这样,是为了防止式子在计算机中浮点数例外。

Code

\(AC\kern 0.5emCODE:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ri register signed
#define p(i) ++i
using namespace std;
namespace IO{
char buf[1<<21],*p1=buf,*p2=buf;
#define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
inline int read() {
ri x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
}
using IO::read;
namespace nanfeng{
#define cmax(x,y) ((x)>(y)?(x):(y))
#define cmin(x,y) ((x)>(y)?(y):(x))
#define FI FILE *IN
#define FO FILE *OUT
typedef double db;
static const int N=55;
static const db eps=1e-8;
db G[N][N],ans=1.0,tmp=1.0;
int n;
inline void Gauss() {
int tr=0;
for (ri i(1);i<=n;p(i)) {
int k=i;
for (ri j(i+1);j<=n;p(j)) if (fabs(G[j][i])>fabs(G[k][i])) k=j;
if (k!=i) swap(G[i],G[k]),tr^=1;
// for (ri j(1);j<=n;p(j)) printf("%.8lf ",G[i][j]);
// puts("");
for (ri j(i+1);j<=n;p(j)) {
db tmp=G[j][i]/G[i][i];
for (ri l(i);l<=n;p(l)) G[j][l]-=tmp*G[i][l];
}
if (fabs(G[i][i])<eps) {ans=0;return;}
ans=ans*G[i][i];
// printf("ans=%.10lf G[i][i]=%.10lf\n",ans,G[i][i]);
}
if (tr) ans=-ans;
}
inline int main() {
// FI=freopen("nanfeng.in","r",stdin);
// FO=freopen("nanfeng.out","w",stdout);
n=read();
for (ri i(1);i<=n;p(i)) {
for (ri j(1);j<=n;p(j)) scanf("%lf",&G[i][j]);
}
for (ri i(1);i<=n;p(i)) {
for (ri j(1);j<=n;p(j)) {
if (G[i][j]<eps) G[i][j]=eps;
if ((1.0-G[i][j])<eps) G[i][j]=1.0-eps;
if (i<j) tmp*=(1.0-G[i][j]);
G[i][j]/=(1.0-G[i][j]);
}
}
// printf("tmp=%.10lf\n",tmp);
for (ri i(1);i<=n;p(i)) {
G[i][i]=0.0;
for (ri j(1);j<=n;p(j)) {
if (i!=j) G[i][i]+=G[i][j],G[i][j]=-G[i][j];
}
}
n-=1;
Gauss();
printf("%.10lf\n",ans*tmp);
return 0;
}
}
int main() {return nanfeng::main();}

题解 P3317 [SDOI2014]重建的更多相关文章

  1. P3317 [SDOI2014]重建(Matrix-tree+期望)

    P3317 [SDOI2014]重建 详情看这位神犇的blog 剩下的注释在code里吧....... #include<iostream> #include<cstdio> ...

  2. P3317 [SDOI2014]重建 变元矩阵树定理 高斯消元

    传送门:https://www.luogu.org/problemnew/show/P3317 这道题的推导公式还是比较好理解的,但是由于这个矩阵是小数的,要注意高斯消元方法的使用: #include ...

  3. 洛谷P3317 [SDOI2014]重建 [Matrix-Tree定理]

    传送门 思路 相信很多人像我一样想直接搞Matrix-Tree定理,而且还过了样例,然后交上去一分没有. 但不管怎样这还是对我们的思路有一定启发的. 用Matrix-Tree定理搞,求出的答案是 \[ ...

  4. P3317 [SDOI2014]重建

    思路 变元矩阵树定理可以统计最小生成树边权积的和,将A矩阵变为边权,D变为与该点相连的边权和,K=D-A,求K的行列式即可 把式子化成 \[ \begin{align}&\sum_{T}\pr ...

  5. 【BZOJ 3534】 3534: [Sdoi2014]重建 (Matrix-Tree Theorem)

    3534: [Sdoi2014]重建 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 709  Solved: 32 ...

  6. BZOJ3534:[SDOI2014]重建——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3534 https://www.luogu.org/problemnew/show/P3317 T国 ...

  7. 【BZOJ3534】【Luogu P3317】 [SDOI2014]重建 变元矩阵树,高斯消元

    题解看这里,主要想说一下以前没见过的变元矩阵树还有前几个题见到的几个小细节. 邻接矩阵是可以带权值的.求所有生成树边权和的时候我们有一个基尔霍夫矩阵,是度数矩阵减去邻接矩阵.而所谓变元矩阵树实际上就是 ...

  8. 【BZOJ 3534】: [Sdoi2014]重建

    题目大意:(略) 题解: 相对误差……我好方. 考虑答案应该为所有合法答案概率之和.对于一个合法的生成树,其出现概率应为所有选取边的概率出现的积 乘以 所有未选取边不出现概率的积. 即: $\;\pr ...

  9. BZOJ3534 [Sdoi2014]重建 【矩阵树定理】

    题目 T国有N个城市,用若干双向道路连接.一对城市之间至多存在一条道路. 在一次洪水之后,一些道路受损无法通行.虽然已经有人开始调查道路的损毁情况,但直到现在几乎没有消息传回. 辛运的是,此前T国政府 ...

随机推荐

  1. DawgCTF wp(re和crypto)

    简单写写思路,想看详解的..我脚本有些丢失了..师傅请移步. 挂了个vpn,算正式打这种国际赛,全是英文.上去打了两天,昨晚晚上划水了一晚上补作业...,re那时候写出来三道,Potentially ...

  2. buu 新年快乐

    一.查壳 发现是upx的壳. 二.拖入ida,发现要先脱壳. 题外话.总结一下手动脱壳,esp定律: 1.先单步到只有esp红色时,右键数据窗口跟随. 2.到数据窗口后,左键硬件访问,byte和wor ...

  3. 比较app版本大小----python

    def compare(a: str, b: str): '''比较两个版本的大小,需要按.分割后比较各个部分的大小''' lena = len(a.split('.')) # 获取版本字符串的组成部 ...

  4. nginx的基本使用

    下载: https://nginx.org/en/download.html  Window下安装: 下载好了之后直接解压就行了.(解压目录切记别含有中文) 启动:1️⃣直接双击nginx.exe2️ ...

  5. RWLock——一种细粒度的Mutex互斥锁

    RWMutex -- 细粒度的读写锁 我们之前有讲过 Mutex 互斥锁.这是在任何时刻下只允许一个 goroutine 执行的串行化的锁.而现在这个 RWMutex 就是在 Mutex 的基础上进行 ...

  6. Spring BeanFactory和现实工厂的对比

    本文不分析Spring的源码流程,只是介绍一些基础的概念,在阅读源码之前,我们应该首先明确研究的对象是什么,才能有的放矢. Spring作为BeanFactory, 和现实工厂有着许多类似之处. 需要 ...

  7. [刘阳Java]_CSS菜单侧边栏制作

    再来写一个菜单侧边栏的制作,先看截图 源代码如下 <!DOCTYPE html> <html> <head> <meta charset="UTF- ...

  8. 03 高性能IO模型:采用多路复用机制的“单线程”Redis

    本篇重点 三个问题: "Redis真的只有单线程吗?""为什么用单线程?""单线程为什么这么快?" "Redis真的只有单线程吗? ...

  9. 【剑指offer】28. 对称的二叉树

    剑指 Offer 28. 对称的二叉树 知识点:二叉树:递归 题目描述 请实现一个函数,用来判断一棵二叉树是不是对称的.如果一棵二叉树和它的镜像一样,那么它是对称的. 示例 输入:root = [1, ...

  10. 微信小程序工具下载与安装

    下载 第一步:百度搜索"微信公众平台" 第二步:登录微信公众平台 第三步:点击微信开发者工具 第四步:按照自己的操作系统下载对应的版本的开发者工具,我的是Windows10 64位 ...