传送门


思路

相信很多人像我一样想直接搞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. SQL中间

    -- 查询门诊挂号退费的账单:有4条记录 select * from `thc_rcm`.`Cs_AccountBill` a where a.orderSource = 1 and a.orderT ...

  2. T-SQL常见基础疑点问答总结

    --建立测试环境 IF object_id('tb') IS NOT NULL     DROP TABLE tb GO   ,),v )) GO INSERT tb SELECT 'a' UNION ...

  3. Mysql 的远程设置 和链接方式

    Mysql 设置远程链接: > grant all privileges on *.* to 用户@localhost identified by '密码'; > flush privil ...

  4. C++ 窗口

    DestroyWindow();     //销毁窗口 可重载的事件: PostNcDestroy    窗口销毁后调用

  5. [Python]基于K-Nearest Neighbors[K-NN]算法的鸢尾花分类问题解决方案

    看了原理,总觉得需要用具体问题实现一下机器学习算法的模型,才算学习深刻.而写此博文的目的是,网上关于K-NN解决此问题的博文很多,但大都是调用Python高级库实现,尤其不利于初级学习者本人对模型的理 ...

  6. Ubuntu下使用Windows应用程序集锦

    QQ & TIM:Wine-QQ-TIM 待续……

  7. Hadoop思维导图之概述

  8. Axure8破解码

    升级了 8.0.0.3321 版本后,原来的 license 失效了,解决方法就是使用下面的这组注册码 License:米 业成 (STUDENT)Key:nFmqBBvEqdvbiUjy8NZiyW ...

  9. markdown自动生成侧边栏TOC /目录

    http://blog.csdn.net/haleypku/article/details/51226704 此文可以只了解一下概念: http://i5ting.github.io/i5ting_z ...

  10. Delphi线程定时器TThreadedTimer及用法--还有TThreadList用法可以locklist

    Delphi线程定时器 - -人生如歌- - 博客园http://www.cnblogs.com/zhengwei0113/p/4192010.html (* 自己编写的线程计时器,没有采用消息机制, ...