BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)
一个点到达终点的期望步数 \(E_i=\sum_{(i,j)\in G}\frac{E_j+1}{out[i]}\),\(out[i]\)为点\(i\)的出度。
那么对于一个DAG可以直接在反向图上拓扑+DP求解。
于是对于环内高斯消元,缩点后拓扑+DP。
无解(无限步)的情况: 起点到不了终点;起点能够走到一个环,且在这个环内无法走到终点(走不出去)。
ps:1.T连出的边不能计算。
2.期望的计算式有个+1!
3.建反向边!
4.重边
注:
如果\(E_i\)表示从起点到点\(i\)的期望步数,那么起点可能多次到达点\(i\),\(E_i\)这个值就。。(可以就直接拿起点做例子?)
如果\(E_i\)表示到达终点的期望步数就没有这个问题。
//21136kb 5168ms
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
const int N=1e4+5,M=1e6+5;
int n,m,S,T,Enum,H[N],to[M],nxt[M],_H[N],_to[M],_nxt[M],in[N],q[N];
int tot,bel[N],scc[N][103],num[N],sz[N],Index,dfn[N],low[N],sk[N],top;
double A[105][105],E[N],out[N];
bool vis[N],vis_s[N],exist[N];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v){
to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;
_to[Enum]=u, _nxt[Enum]=_H[v], _H[v]=Enum;
}
void Tarjan(int x)
{
dfn[x]=low[x]=++Index, sk[++top]=x, exist[x]=1;
for(int i=H[x]; i; i=nxt[i])
if(!dfn[to[i]]) Tarjan(to[i]),low[x]=std::min(low[x],low[to[i]]);
else if(exist[to[i]]) low[x]=std::min(low[x],dfn[to[i]]);
if(dfn[x]==low[x])
{
++tot;
do
{
bel[sk[top]]=tot, num[sk[top]]=sz[tot],
scc[tot][sz[tot]++]=sk[top], exist[sk[top--]]=0;
}while(sk[top+1]!=x);
}
}
void DFS(int x)
{
vis[x]=vis_s[bel[x]]=1;
if(x==T) return;//有没有都行
for(int i=H[x]; i; i=nxt[i])
if(!vis[to[i]]) /*++in[bel[x]],//Wrong*/DFS(to[i]);
}
void Gauss(int n)
{
for(int j=0; j<n; ++j)
{
int mxrow=j;
for(int i=j+1; i<n; ++i)
if(fabs(A[i][j])>fabs(A[mxrow][j])) mxrow=i;
if(mxrow!=j) for(int k=0; k<=n; ++k) std::swap(A[mxrow][k],A[j][k]);
for(int i=j+1; i<n; ++i)
if(A[i][j])
{
double t=A[i][j]/A[j][j];
for(int k=j; k<=n; ++k)
A[i][k]-=A[j][k]*t;
}
}
for(int i=n-1; ~i; --i)
{
for(int j=i+1; j<n; ++j) A[i][n]-=A[i][j]*A[j][n];
A[i][n]/=A[i][i];
}
}
int main()
{
n=read(),m=read(),S=read(),T=read();
for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),out[u]+=1.0,AddEdge(u,v);
for(int i=1; i<=n; ++i)
if(!dfn[i]) Tarjan(i);
DFS(S);
if(!vis[T]) {puts("INF"); return 0;}
for(int x=1; x<=n; ++x)
for(int i=H[x]; i; i=nxt[i])
if(bel[x]!=bel[to[i]]) ++in[bel[x]];//反向图上的入度+1。
for(int i=1; i<=tot; ++i)
if(vis_s[i]&&!in[i]&&bel[T]!=i) {puts("INF"); return 0;}
for(int i=1; i<=n; ++i) out[i]=1.0/out[i];
int h=0,t=0;
q[t++]=bel[T];
// for(int i=1; i<=tot; ++i)
// if(!in[i]) q[t++]=i;//in[]=0的只能是bel[T].
while(h<t)
{
int now=q[h++];
memset(A,0,sizeof A);
for(int j=0; j<sz[now]; ++j)
{
int x=scc[now][j];
A[j][j]=1.0, A[j][sz[now]]=E[x]/*之前加上的*/;
if(x==T) continue;//不计算终点连出的边!
for(int i=H[x]; i; i=nxt[i])
if(bel[to[i]]==now){
A[j][sz[now]]+=out[x],//步数+1.
A[j][num[to[i]]]-=out[x];//是点的出度不是in[]! //-=不能直接赋值=:有重边!
}
}
Gauss(sz[now]);
for(int j=0; j<sz[now]; ++j)
{
int x=scc[now][j];
E[x]=A[j][sz[now]];
for(int i=_H[x]; i; i=_nxt[i])
if(bel[_to[i]]!=now){
if(!--in[bel[_to[i]]]) q[t++]=bel[_to[i]];
E[_to[i]]+=(E[x]+1)*out[_to[i]];
}
}
}
printf("%.3lf",E[S]);
return 0;
}
BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)的更多相关文章
- bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)
Description Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿 ...
- BZOJ2707: [SDOI2012]走迷宫(期望 tarjan 高斯消元)
题意 题目链接 Sol 设\(f[i]\)表示从\(i\)走到\(T\)的期望步数 显然有\(f[x] = \sum_{y} \frac{f[y]}{deg[x]} + 1\) 证明可以用全期望公式. ...
- BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元
BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...
- BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )
数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了. E(u) = 1 + Σ E(v) / degree(u) 对拍时发现网上2个程序的INF判断和我不一 ...
- BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]
2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...
- BZOJ 2707: [SDOI2012]走迷宫 拓扑+高斯消元+期望概率dp+Tarjan
先Tarjan缩点 强连通分量里用高斯消元外面直接转移 注意删掉终点出边和拓扑 #include<cstdio> #include<cstring> #include<a ...
- bzoj千题计划289:bzoj 2707: [SDOI2012]走迷宫
http://www.lydsy.com/JudgeOnline/problem.php?id=2707 dp[i] 表示从点i到终点的期望步数 dp[i]= Σ (dp[j]+1)/out[i] j ...
- ZJUT 1423 地下迷宫(期望DP&高斯消元)
地下迷宫 Time Limit:1000MS Memory Limit:32768K Description: 由于山体滑坡,DK被困在了地下蜘蛛王国迷宫.为了抢在DH之前来到TFT,DK必须尽快走 ...
- BZOJ 4820 [Sdoi2017]硬币游戏 ——期望DP 高斯消元
做法太神了,理解不了. 自己想到的是建出AC自动机然后建出矩阵然后求逆计算,感觉可以过$40%$ 用一个状态$N$表示任意一个位置没有匹配成功的概率和. 每种匹配不成功的情况都是等价的. 然后我们强制 ...
随机推荐
- 【转】Python中的eval()、exec()及其相关函数
[转]Python中的eval().exec()及其相关函数 刚好前些天有人提到eval()与exec()这两个函数,所以就翻了下Python的文档.这里就来简单说一下这两个函数以及与它们相关的几个函 ...
- Ubuntu 分辨率显示出错,分辨率不是最佳分辨率的解决办法
本文为转载,但在Ubuntu16.04LTS下亲测有效. (1)首先使用 xrandr 命令列出当前所能检测到的分辨率,如一台显示器,最佳分辨率为 1440x900(我的显示器尽量设置1680x105 ...
- mysql系列六、mysql创建用户、授权、备份及恢复命令
一.创建用户和授权 下面的操作中,其中someusername为用户名,somepassword为密码,somedbname为数据库名 1.创建用户 create user 'someusername ...
- SharePoint 2010:“&”作为SharePoint账号密码引起的错误
一朋友修改了SharePoint 2010系统账号密码,导致无法登陆.他的环境如下: 两台服务器:AD+SharePoint 2010 ,Sql Server 2008 r2 目标站点开启了Form登 ...
- centos6.5环境下zookeeper-3.4.6集群环境部署及单机部署详解
centos6.5环境下Zookeeper-3.4.6集群环境部署 [系统]Centos 6.5 集群部署 [软件]准备好jdk环境,此次我们的环境是open_jdk1.8.0_101 zookeep ...
- LeetCode(54):螺旋矩阵
Medium! 题目描述: 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, ...
- PHP数组序列化和反序列化
PHP序列化在我们实际项目运行过程中是一种非常常见的操作.比如当我们想要将数组值存储到数据库时,就可以对数组进行序列化操作,然后将序列化后的值存储到数据库中.其实PHP序列化数组就是将复杂的数组数据类 ...
- poj3585 树形dp 二次扫描,换根法模板题
#include<iostream> #include<cstring> #include<cstdio> #include<vector> using ...
- (无)webservice执行过程深入理解
前面我们搞了1,2个DEMO,基本对webservice服务发布,调用 ,执行 有一定的了解. 今天的话,我们再系统的梳理下webservice执行过程. 首先我们在webservice服务器端开发w ...
- pytest五:fixture_autouse=True
平常写自动化用例会写一些前置的 fixture 操作,用例需要用到就直接传该函数的参数名称就行了.当用例很多的时候,每次都传返个参数,会比较麻烦.fixture 里面有个参数 autouse,默讣是 ...