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$表示任意一个位置没有匹配成功的概率和. 每种匹配不成功的情况都是等价的. 然后我们强制 ...
随机推荐
- MAC上mongodb连接不上
1.在Mac客户端里输入 mongo,发现mongo连接不上了,原因是mongo的服务没有开启. 2.在命令行了输入 mongod,开启服务的命令 3.启动起来以后,用mongo连接服务器.
- 文件&报表状态ID
def_filestatus Uploading=4 WaitingParse=6 Parsing=10 Completed=14 ParseError=1006 UploadError=1004 d ...
- 汇编语言转换成c语言,或者汇编语言转换成golang的汇编,c语言转换成golang的方法
https://github.com/minio/c2goasm http://microapl.com/asm2c/index.html 收费的 https://gith ...
- mysql系列五、mysql中having的用法
HAVING 子句对 GROUP BY 子句设置条件的方式与 WHERE 和 SELECT 的交互方式类似.WHERE 搜索条件在进行分组操作之前应用:而HAVING 搜索条件在进行分组操作之后应用. ...
- softlab对接Jenkins工程
在Softlab上对接jenkins工程,必须先在自己的jenkins环境上配置好任务. 1.登陆到jenkins首页,比如http://10.179.175.53:8080/jenkins/ 2.点 ...
- R-FCN:安装训练自己的数据
参考:http://blog.csdn.net/sinat_30071459/article/details/53202977 如果用的是cudnnv5,可能会遇到问题,下载最新的caffe,替换这部 ...
- opencv error: insufficient memory错误解决办法
用opencv合成图像时出现的错误,大概4000多张会报错,在网上查阅一些博客时才知道原因.之前编译的时候用的是x86,切换到x64下可解决问题,具体: 1.项目->属性->配置管理器-& ...
- ZOJ 3229 Shoot the Bullet(有源汇上下界最大流)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3442 题目大意: 一个屌丝给m个女神拍照,计划拍照n天,每一天屌丝给 ...
- python接口自动化测试十七:使用bs4框架进行简单的爬虫
安装:beautifulsoup4 from bs4 import BeautifulSoup yoyo = open('yoyo.html', 'r') # 以读的方式打开“yoyo.html” ...
- C# int可以表示的最大值
C#中int由4个字节组成,即由32个二进制数组成,由于最高位是用于表示正负数,所以实际上int所能表示的最大数为231-1=2147483647.