洛谷P3317 [SDOI2014]重建 [Matrix-Tree定理]
思路
相信很多人像我一样想直接搞Matrix-Tree定理,而且还过了样例,然后交上去一分没有。
但不管怎样这还是对我们的思路有一定启发的。
用Matrix-Tree定理搞,求出的答案是
\]
其中\(W_e\)表示我们给\(e\)赋的权值,现在还不知道是啥。
然而,我们要的答案却是这样的:
\]
其中\(w_e\)表示边\(e\)存在的概率。
注意到区别了吗?现在就要尝试去除区别。
考虑这样一个式子:
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定理]的更多相关文章
- BZOJ 3534: [Sdoi2014]重建(Matrix Tree)
		
传送门 解题思路 比较容易看的出来矩阵树定理.然后就怒送一Wa,这个矩阵树定理是不能直接用的.题目要求的其实是这个玩意. \[ ans=\sum\limits_{Tree}( \prod\limits ...
 - 洛谷3317 SDOI2014重建(高斯消元+期望)
		
qwq 一开始想了个错的做法. 哎 直接开始说比较正确的做法吧. 首先我们考虑题目的\(ans\)该怎么去求 我们令\(x\)表示原图中的某一条边 \[ans = \sum \prod_{x\in t ...
 - @总结 - 7@ 生成树计数 —— matrix - tree 定理(矩阵树定理)与 prüfer 序列
		
目录 @0 - 参考资料@ @0.5 - 你所需要了解的线性代数知识@ @1 - 矩阵树定理主体@ @证明 part - 1@ @证明 part - 2@ @证明 part - 3@ @证明 part ...
 - P3317 [SDOI2014]重建(Matrix-tree+期望)
		
P3317 [SDOI2014]重建 详情看这位神犇的blog 剩下的注释在code里吧....... #include<iostream> #include<cstdio> ...
 - BZOJ.4031.[HEOI2015]小Z的房间(Matrix Tree定理 辗转相除)
		
题目链接 辗转相除解行列式的具体实现? 行列式的基本性质. //864kb 64ms //裸的Matrix Tree定理.练习一下用辗转相除解行列式.(因为模数不是质数,所以不能直接乘逆元来高斯消元. ...
 - [bzoj1016][JSOI2008]最小生成树计数 (Kruskal + Matrix Tree 定理)
		
Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...
 - 洛谷P4198 楼房重建 (分块)
		
洛谷P4198 楼房重建 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题, ...
 - 【证明与推广与背诵】Matrix Tree定理和一些推广
		
[背诵手记]Matrix Tree定理和一些推广 结论 对于一个无向图\(G=(V,E)\),暂时钦定他是简单图,定义以下矩阵: (入)度数矩阵\(D\),其中\(D_{ii}=deg_i\).其他= ...
 - 数学-Matrix Tree定理证明
		
老久没更了,冬令营也延期了(延期后岂不是志愿者得上学了?) 最近把之前欠了好久的债,诸如FFT和Matrix-Tree等的搞清楚了(啊我承认之前只会用,没有理解证明--),FFT老多人写,而Matri ...
 
随机推荐
- spring注解第05课 FactoryBean
			
1.工厂bean调用 @Configuration public class MainConfig2 {/** * 使用Spring提供的 FactoryBean(工厂Bean); * 1).默认获取 ...
 - 使用js请求Servlet时的路径
			
项目结构如下: 全是web的html页面 js部分重要代码: function ajaxValidate() { var flag=false; $.ajax({ "url":&q ...
 - 二十三、Linux 进程与信号---进程链和进程扇、守护进程和孤儿进程以及僵尸进程
			
23.1 进程链和进程扇 23.1.1 概念 进程链:一个父进程构建出一个子进程,子进程再构建出子子进程,子子进程构建出子子子进程.... 这种就为进程链 进程扇:一个父进程构建出多个子进程,子进程都 ...
 - 二十二、Linux 进程与信号---进程创建(续)
			
22.2 父子进程操作文件 文件操作由两种模式: IO 系统调用操作文件 标准C IO 操作文件 看代码: #include <unistd.h> #include <string. ...
 - 十三、u-boot 调试-- NOR FLASH 支持
			
13.1 问题现象 在烧写进去的u-boot 中 Flash 并没有显示实际大小,需要进行修改. 13.2 问题定位过程 13.2.1 关键字搜索 Flash: 此关键字在 Board_r.c (co ...
 - tarjan强连通算法
			
#include <iostream> #include <string.h> using namespace std; ; ; struct edge{ int v,next ...
 - 词根 sent/sens
			
sense--> to feel (来自于拉丁语 sensus) 词根sent/sens 表示感知 sentiment 感情 consent consensus con- 一起, 一起的感 ...
 - 第25月第7天 聚宽 svm
			
1. # 克隆自聚宽文章:https://www.joinquant.com/post/2709 # 标题:基于SVM的机器学习策略 # 作者:走得很慢的海龟 import math import n ...
 - 【转载】java abstract class和interface的区别
			
转载:https://blog.csdn.net/b271737818/article/details/3950245 在Java语言中,abstract class和interface是支持抽象类定 ...
 - java多线程面试题小结
			
http://www.importnew.com/12773.html http://www.cnblogs.com/fingerboy/p/5352880.html https://blog.csd ...