传送门


思路

相信很多人像我一样想直接搞Matrix-Tree定理,而且还过了样例,然后交上去一分没有。

但不管怎样这还是对我们的思路有一定启发的。

用Matrix-Tree定理搞,求出的答案是

\[t=\sum_{E\;is\;a\;tree} \prod_{e\in E} W_e
\]

其中\(W_e\)表示我们给\(e\)赋的权值,现在还不知道是啥。

然而,我们要的答案却是这样的:

\[ans=\sum_{E\;is\;a\;tree} \prod_{e\in E} w_e \prod_{e\notin E} (1-w_e)
\]

其中\(w_e\)表示边\(e\)存在的概率。

注意到区别了吗?现在就要尝试去除区别。

考虑这样一个式子:

\[\begin{align*}
ans&=t\times \prod_{e} (1-w_e)\\
&=\sum_{E\;is\;a\;tree} \prod_{e\in E} W_e \prod_{e} (1-w_e)\\
&=\sum_{E\;is\;a\;tree} \prod_{e\in E} W_e(1-w_e) \prod_{e\notin E} (1-w_e)\\
\end{align*}
\]

是不是超棒?

于是有了一个方程:\(W_e(1-w_e)=w_e\),得到\(W_e=\frac{w_e}{1-w_e}\),Matrix-Tree定理往上套即可。

还要注意一个问题:\(1-w_e<eps\)时会有除零的情况发生,此时要强行设\(w_e=1-eps\)以避免。


代码

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
using namespace std;
#define pii pair<int,int>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define templ template<typename T>
#define sz 60
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templ inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(register int x)
{
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
}
inline void chktime()
{
#ifndef ONLINE_JUDGE
cout<<(clock()-t)/1000.0<<'\n';
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std; const db eps=1e-9; int n;
db a[sz][sz]; db A[sz][sz];
void add(int x,int y,db w){A[x][x]+=w;A[y][y]+=w;A[x][y]-=w;A[y][x]-=w;}
db calc(int n)
{
db ans=1;
rep(i,1,n)
{
if (!A[i][i])
{
int tmp=-1;
rep(j,i+1,n) if (fabs(A[j][i])>eps) tmp=j;
if (tmp==-1) return 0;
swap(A[i],A[tmp]);
}
db I=1.0/A[i][i];
rep(j,i+1,n) if (A[j][i])
{
db t=I*A[j][i];
rep(k,i,n) A[j][k]-=A[i][k]*t;
}
ans=ans*A[i][i];
}
return ans;
} int main()
{
file();
read(n);
db ans=1;
rep(i,1,n) rep(j,1,n)
{
read(a[i][j]);
if (a[i][j]>1-eps) a[i][j]=1-eps;
ans*=(1-a[i][j]),a[i][j]/=(1-a[i][j]);
}
ans=sqrt(ans);
rep(i,1,n) rep(j,1,i-1) add(i,j,a[i][j]);
ans*=calc(n-1);
cout<<ans;
return 0;
}

洛谷P3317 [SDOI2014]重建 [Matrix-Tree定理]的更多相关文章

  1. BZOJ 3534: [Sdoi2014]重建(Matrix Tree)

    传送门 解题思路 比较容易看的出来矩阵树定理.然后就怒送一Wa,这个矩阵树定理是不能直接用的.题目要求的其实是这个玩意. \[ ans=\sum\limits_{Tree}( \prod\limits ...

  2. 洛谷3317 SDOI2014重建(高斯消元+期望)

    qwq 一开始想了个错的做法. 哎 直接开始说比较正确的做法吧. 首先我们考虑题目的\(ans\)该怎么去求 我们令\(x\)表示原图中的某一条边 \[ans = \sum \prod_{x\in t ...

  3. @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列

    目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...

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

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

  5. BZOJ.4031.[HEOI2015]小Z的房间(Matrix Tree定理 辗转相除)

    题目链接 辗转相除解行列式的具体实现? 行列式的基本性质. //864kb 64ms //裸的Matrix Tree定理.练习一下用辗转相除解行列式.(因为模数不是质数,所以不能直接乘逆元来高斯消元. ...

  6. [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)

    Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...

  7. 洛谷P4198 楼房重建 (分块)

    洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...

  8. 【证明与推广与背诵】Matrix Tree定理和一些推广

    [背诵手记]Matrix Tree定理和一些推广 结论 对于一个无向图\(G=(V,E)\),暂时钦定他是简单图,定义以下矩阵: (入)度数矩阵\(D\),其中\(D_{ii}=deg_i\).其他= ...

  9. 数学-Matrix Tree定理证明

    老久没更了,冬令营也延期了(延期后岂不是志愿者得上学了?) 最近把之前欠了好久的债,诸如FFT和Matrix-Tree等的搞清楚了(啊我承认之前只会用,没有理解证明--),FFT老多人写,而Matri ...

随机推荐

  1. spring注解第05课 FactoryBean

    1.工厂bean调用 @Configuration public class MainConfig2 {/** * 使用Spring提供的 FactoryBean(工厂Bean); * 1).默认获取 ...

  2. 使用js请求Servlet时的路径

    项目结构如下: 全是web的html页面 js部分重要代码: function ajaxValidate() { var flag=false; $.ajax({ "url":&q ...

  3. 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程

    23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...

  4. 二十二、Linux 进程与信号---进程创建(续)

    22.2 父子进程操作文件 文件操作由两种模式: IO 系统调用操作文件 标准C IO 操作文件 看代码: #include <unistd.h> #include <string. ...

  5. 十三、u-boot 调试-- NOR FLASH 支持

    13.1 问题现象 在烧写进去的u-boot 中 Flash 并没有显示实际大小,需要进行修改. 13.2 问题定位过程 13.2.1 关键字搜索 Flash: 此关键字在 Board_r.c (co ...

  6. tarjan强连通算法

    #include <iostream> #include <string.h> using namespace std; ; ; struct edge{ int v,next ...

  7. 词根 sent/sens

    sense--> to feel (来自于拉丁语 sensus) 词根sent/sens 表示感知 sentiment 感情 consent   consensus  con- 一起, 一起的感 ...

  8. 第25月第7天 聚宽 svm

    1. # 克隆自聚宽文章:https://www.joinquant.com/post/2709 # 标题:基于SVM的机器学习策略 # 作者:走得很慢的海龟 import math import n ...

  9. 【转载】java abstract class和interface的区别

    转载:https://blog.csdn.net/b271737818/article/details/3950245 在Java语言中,abstract class和interface是支持抽象类定 ...

  10. java多线程面试题小结

    http://www.importnew.com/12773.html http://www.cnblogs.com/fingerboy/p/5352880.html https://blog.csd ...