题意

题目链接

Sol

设\(f[i]\)表示从\(i\)走到\(T\)的期望步数

显然有\(f[x] = \sum_{y} \frac{f[y]}{deg[x]} + 1\)

证明可以用全期望公式。

那么我们可以把每个强联通分量里的点一起高斯消元,就做完了。

(warning:BZOJ没有C++11,但是下面的代码是正确的,至于为什么可以点题目链接。。。。)

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 10;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, M, S, T;
int dfn[MAXN], low[MAXN], vis[MAXN], tot, cnt, inder[MAXN], col[MAXN], ha[MAXN];
double f[201][201], deg[MAXN], ans[MAXN];
stack<int> s;
vector<int> v[MAXN], scc[MAXN], E[MAXN];
void Pre() {
for(int i = 1; i <= N; i++) {
double sum = 0; f[i][i] = 1.0;
for(auto &x : v[i])
if(x != T) sum += 1.0 / deg[x], f[i][x] = -1.0;
f[i][N + 1] = sum;
}
}
void Gauss(int n) {
for(int i = 1; i <= n; i++) {
int mx = i;
for(int j = i + 1; j <= n; j++) if(f[j][i] > f[mx][i]) mx = j;
if(i != mx) swap(f[i], f[mx]);
for(int j = 1; j <= n; j++) {
if(i == j) continue;
double p = f[j][i] / f[i][i];
for(int k = i + 1; k <= n + 1; k++) f[j][k] -= f[i][k] * p;
}
}
for(int i = 1; i <= n; i++) f[i][n + 1] = f[i][n + 1] / f[i][i];
}
void Tarjan(int x) {
dfn[x] = low[x] = ++tot; s.push(x); vis[x] = 1;
for(auto &to : v[x]) {
if(!dfn[to]) Tarjan(to), low[x] = min(low[x], low[to]);
else if(vis[to]) low[x] = min(low[x], dfn[to]);
}
if(low[x] == dfn[x]) {
int h; cnt++;
do {
h = s.top(); s.pop();
vis[h] = 0;
scc[cnt].push_back(h);
col[h] = cnt;
}while(h != x);
}
}
void solve(vector<int> &p) {
memset(vis, 0, sizeof(vis));
memset(f, 0, sizeof(f)); int num = p.size();
for(int i = 0; i < p.size(); i++) vis[p[i]] = i + 1;
for(int i = 0; i < p.size(); i++) {
int x = p[i];
f[i + 1][i + 1] = deg[x]; f[i + 1][num + 1] = deg[x];
for(auto &to : v[x]) {
if(vis[to]) f[i + 1][vis[to]] -= 1;
else f[i + 1][num + 1] += ans[to];
}
}
Gauss(num);
for(int i = 0; i < p.size(); i++) ans[p[i]] = f[i + 1][num + 1];
}
void Topsort() {
queue<int> q; q.push(col[T]);
while(!q.empty()) {
int p = q.front(); q.pop();
for(auto &to : E[p]) if(!(--inder[to])) q.push(to);
if(p != col[T])
solve(scc[p]);
}
}
int main() {
N = read(); M = read(); S = read(); T = read();
for(int i = 1; i <= M; i++) {
int x = read(), y = read();
if(x != T) v[x].push_back(y), deg[x]++;
}
Tarjan(S);
if(!dfn[T]) {puts("INF"); return 0;}
for(int i = 1; i <= N; i++) {
for(auto &x : v[i])
if(col[i] != col[x])
inder[col[i]]++, E[col[x]].push_back(col[i]);
}
for(int i = 1; i <= cnt; i++) if(i != col[T] && !inder[i]) {puts("INF"); return 0;}
Topsort();
printf("%.3lf", ans[S]);
return 0;
}

BZOJ2707: [SDOI2012]走迷宫(期望 tarjan 高斯消元)的更多相关文章

  1. BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)

    题目链接 一个点到达终点的期望步数 \(E_i=\sum_{(i,j)\in G}\frac{E_j+1}{out[i]}\),\(out[i]\)为点\(i\)的出度. 那么对于一个DAG可以直接在 ...

  2. bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)

    Description Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿 ...

  3. BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元

    BZOJ_3143_[Hnoi2013]游走_期望DP+高斯消元 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机 ...

  4. ZJUT 1423 地下迷宫(期望DP&高斯消元)

    地下迷宫 Time Limit:1000MS  Memory Limit:32768K Description: 由于山体滑坡,DK被困在了地下蜘蛛王国迷宫.为了抢在DH之前来到TFT,DK必须尽快走 ...

  5. BZOJ2707 [SDOI2012]走迷宫 【概率dp + tarjan + 高斯消元】

    题目 Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的 ...

  6. BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )

    数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了. E(u) = 1 + Σ E(v) / degree(u) 对拍时发现网上2个程序的INF判断和我不一 ...

  7. 【BZOJ3143】[Hnoi2013]游走 期望DP+高斯消元

    [BZOJ3143][Hnoi2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 ...

  8. bzoj3143 游走 期望dp+高斯消元

    题目传送门 题意: 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得 ...

  9. BZOJ2707 : [SDOI2012]走迷宫

    首先求出SCC缩点,E[T]=0,按拓扑序计算 对于无边连出的块,如果不是T所在块,则称该块是死路块 对于一个块,如果其中的点连出的边是死路块,则它也是死路块 否则对于每块进行高斯消元求出期望 如果S ...

随机推荐

  1. Python小白学习之路(二十六)—【if __name__ =='__main__':】【用状态标识操作】

    规则一: 一个python文件中,只写一些可以运行的功能测试代码写在这句代码下面 if __name__ =='__main__': 在讲这边的时候,我不是很懂参考了一篇博客,地址如下:http:// ...

  2. python3 调用 salt-api

    使用python3调用 salt-api 在项目中我们不能使用命令行的模式去调用salt-api,所以我们可以写一个基于salt-api的类,方便项目代码的调用.在这里特别附上两种方式实现的pytho ...

  3. vue教程1-05 事件 简写、事件对象、冒泡、默认行为、键盘事件

    vue教程1-05 事件 简写.事件对象.冒泡.默认行为.键盘事件 v-on:click/mouseover...... 简写的: @click="" 推荐 事件对象: @clic ...

  4. 编写一个c++工程

    c++接触的很少,之前也只是会编写一个简单的cpp文件,但一个工程的实现,往往不仅包括源文件(.cpp后缀文件)一般还有头文件(.h后缀文件)等.一个c++工程中只能有一个main函数,这个函数所在的 ...

  5. 字符、字符串和文本的处理之Char类型

    .Net Framework中处理字符和字符串的主要有以下这么几个类: (1).System.Char类 一基础字符串处理类 (2).System.String类 一处理不可变的字符串(一经创建,字符 ...

  6. COM+时代的自动事务

    最近看公司的遗留项目代码,调试的时候发现经常报分布式事务错误,可是整个代码里没有看见开启过事务,于是开始研究,发现了这个.Net Framework1.1时代的产物. namespace Busine ...

  7. Docker概念学习系列之Docker与传统虚拟机差异(4)

    不多说,直接上干货! 见[博主]撰写的https://mp.weixin.qq.com/s/YihjPONUcUi4b_7RC8oLYw   传统虚拟化是在硬件层面实现虚拟化,需要有额外的虚拟机管理应 ...

  8. 谈谈Linux下的数据流重定向和管道命令

    一.标准输入.标准输出.错误输出概述 1.标准输入(stdin)是指令数据的输入,代码为0,使用<或者<<,默认是键盘. 2.标准输出(stdout)是指令执行成功返回的结果,代码为 ...

  9. 前端通信:ajax设计方案(九)--- 完善文档

    ajax-js 1.9.1 文档 目录 * common(options, isCreatePoll) * config(options) * get(url, data, successEvent, ...

  10. “声讨”高云的《jQuery技术内幕》

    1. 前言: 其实本文有点太标题党了,哈哈,见谅.说“声讨”,就是说说我作为一个<jQuery技术内幕>一个忠实读者,读本书的一些想法和建议. 2014年2月20日,我收到了<jQu ...