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$表示任意一个位置没有匹配成功的概率和. 每种匹配不成功的情况都是等价的. 然后我们强制 ...
随机推荐
- 【网络编程4】网络编程基础-ARP响应(ARP欺骗之中间人攻击)
arp欺骗->arp响应 ARP 缓存中毒(ARP欺骗) arp传送原理在于主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址:收到返回消 ...
- Python中的__init__()和__call__()函数
Python中的__init__()和__call__()函数 在Python的class中有一些函数往往具有特殊的意义.__init__()和__call__()就是class很有用的两类特殊的函数 ...
- 转载 - CNN感受野(receptive-fields)RF
本文翻译自A guide to receptive field arithmetic for Convolutional Neural Networks(可能需要FQ才能访问),方便自己学习和参考.若 ...
- 蓝牙HID协议笔记【转】
蓝牙HID协议笔记 转自:http://blog.sina.com.cn/s/blog_69b5d2a50101emll.html 1.概述 The Human Interface Devic ...
- javascript 什么类型没有toString()?
JS里面任何对象都有toString()方法么?不是! null和undefined就没有!虽然null用typeof看的时候,是object类型的. 另外number对象调用toString()会报 ...
- Oracle查询表主键、外键
项目中用到的一些Sql(oracle下的)总结: 1.查找表的所有索引(包括索引名,类型,构成列) select t.*,i.index_type from user_ind_columns t,us ...
- 【splunk】数据输入-文件目录 导入失败
今天用splunk的“数据输入-文件目录”自动监控文件并索引,结果失败了,完全没有出现我要的索引. 解决: 删除文件监控 改为一次性索引 再重新添加连续监控 原因: 尚不明确 https://answ ...
- 【mysql】表备份
几个讲得比较好的资料: http://www.cnblogs.com/liangshaoye/p/5464794.html:讲解了热备,温备,冷备,增量备份,差异备份等多种概念. http://www ...
- 使用@property - 廖雪峰的官方网站
使用@property 阅读: 20616 在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9 ...
- js 事件对象
/* 事件绑定的格式: 元素节点.on + 事件类型 = function(){ } 元素节点 事件类型 on+事件类型:事件处理函数 [注]上述三者一绑定:生成一个新的事件对象. [注]触发事件以后 ...