[SDOI2012]走迷宫 (强连通分量缩点,动态规划,高斯消元)
题面
Morenan被困在了一个迷宫里。迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T。可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的有向边,到达另一个点。这样,Morenan走的步数可能很长,也可能是无限,更可能到不了终点。若到不了终点,则步数视为无穷大。但你必须想方设法求出Morenan所走步数的期望值。
N<=10000,M<=1000000,保证强连通分量的大小不超过 200。
题解
做法没什么好细说的,
就是缩点,然后按照拓扑序倒着求每个强连通分量的 DP 值(每个点出发的期望步数),强连通分量内部用高斯消元。如果存在概率走入一个死环(无法走到终点的强连通分量),那么就无穷大。
剩下的就是一些细节:
没必要真的求拓扑序,只需要按照 dfs 序倒着来,也就是 Tarjan 缩点产生强连通分量的正顺序来就行了。
解方程如果无解,说明期望步数无穷大。
解方程之前注意清空(包括 size+1 列),注意各种标号。
CODE
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1000005
#define LL long long
#define DB double
#define lowbit(x) (-(x) & (x))
#define ENDL putchar('\n')
#define FI first
#define SE second
#define eps 1e-9
LL read() {
LL f=1,x=0;int s = getchar();
while(s < '0' || s > '9') {if(s<0) return -1;if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar('0'+(x%10));}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) {putchar('-');x = -x;}
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
const int MOD = 1000000007;
int n,m,s,o,k;
int od[MAXN],S,T;
int hd[MAXN],v[MAXN<<1],nx[MAXN<<1],cne;
void ins(int x,int y) {
nx[++ cne] = hd[x]; v[cne] = y; hd[x] = cne;
}
int dfn[MAXN],low[MAXN],tim;
bool f[MAXN];
int fail[MAXN];
stack<int> st;
int bel[MAXN],cnt;
vector<int> bu[MAXN];
int rk[MAXN];
void dfs0(int x) {
low[x] = dfn[x] = ++ tim;
st.push(x); f[x] = 1;
for(int i = hd[x];i;i = nx[i]) {
int y = v[i];
if(!dfn[y]) {
dfs0(y);
low[x] = min(low[x],low[y]);
}
else if(f[y]) {
low[x] = min(low[x],dfn[y]);
}
}
if(low[x] == dfn[x]) {
fail[++ cnt] = -1;
while(f[x]) {
int t = st.top(); st.pop();
f[t] = 0;
bel[t] = cnt;
bu[cnt].push_back(t);
rk[t] = bu[cnt].size();
}
}
return ;
}
DB a[205][205],dp[MAXN];
DB Abs(DB x) {return x < 0 ? -x:x;}
int Gauss(int n) {
for(int i = 1;i <= n;i ++) {
for(int j = i+1;j <= n;j ++) {
if(Abs(a[j][i]) > Abs(a[i][i])) {
swap(a[i],a[j]);
}
}
if(Abs(a[i][i]) < eps) continue;
for(int j = i+1;j <= n;j ++) {
DB nm = a[j][i] / a[i][i];
for(int k = n+1;k >= i;k --) {
a[j][k] -= a[i][k] * nm;
}
}
}
for(int i = n;i > 0;i --) {
for(int j = n;j > i;j --) {
a[i][n+1] -= a[i][j] * a[j][n+1];
a[i][j] = 0;
}
if(!a[i][i]) return 1;
a[i][n+1] /= a[i][i];
a[i][i] = 1;
}
return 0;
}
int main() {
n = read(); m = read();
S = read(); T = read();
for(int i = 1;i <= m;i ++) {
s = read();o = read();
ins(s,o); od[s] ++;
}
for(int i = 1;i <= n;i ++) {
if(!dfn[i]) {
dfs0(i);
}
}
for(int i = 1;i <= cnt;i ++) {
int sz = bu[i].size();
for(int j = 1;j <= sz;j ++) {
for(int k = 1;k <= sz+1;k ++) a[j][k] = 0;
}
for(int j = 1;j <= sz;j ++) {
a[j][j] = 1.0;
}
for(int j = 0;j < sz;j ++) {
int x = bu[i][j];
if(x == T) continue;
if(!od[x]) {
fail[i] = 1; break;
}
a[rk[x]][sz+1] += 1.0;
for(int k = hd[x];k;k = nx[k]) {
int y = v[k];
if(y == T) a[rk[x]][sz+1] += 1.0/od[x] * dp[T];
else if(bel[y] != i) {
if(fail[bel[y]] > 0) {fail[i] = 1;break;}
a[rk[x]][sz+1] += 1.0/od[x] * dp[y];
}
else {
a[rk[x]][rk[y]] -= 1.0/od[x];
}
}
if(fail[i] > 0) break;
}
if(fail[i] > 0) continue;
fail[i] = Gauss(sz);
for(int j = 0;j < sz;j ++) {
int x = bu[i][j];
dp[x] = a[rk[x]][sz+1];
}
}
if(fail[bel[S]] > 0) printf("INF\n");
else printf("%.3f\n",dp[S]);
return 0;
}
``
[SDOI2012]走迷宫 (强连通分量缩点,动态规划,高斯消元)的更多相关文章
- BZOJ_1778_[Usaco2010_Hol]_Dotp_驱逐猪猡_(期望动态规划+高斯消元+矩阵)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1778 炸弹从1出发,有\(\frac{P}{Q}\)的概率爆炸,如果不爆炸,等概率移动到连通的 ...
- 洛谷 P5643 - [PKUWC2018]随机游走(Min-Max 容斥+FWT+树上高斯消元,hot tea)
题面传送门 一道挺综合的 hot tea,放到 PKUWC 的 D2T2 还挺喜闻乐见的( 首先我们考虑怎样对一个固定的集合 \(S\) 计算答案,注意到我们要求的是一个形如 \(E(\max(S)) ...
- BZOJ_3270_博物馆_(高斯消元+期望动态规划+矩阵)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3270 \(n\)个房间,刚开始两个人分别在\(a,b\),每分钟在第\(i\)个房间有\(p[ ...
- uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=sh ...
- BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]
2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...
- 洛谷 P6030 - [SDOI2012]走迷宫(高斯消元+SCC 缩点)
题面传送门 之所以写个题解是因为题解区大部分题解的做法都有 bug(u1s1 周六上午在讨论区里连发两个 hack 的是我,由于我被禁言才让 ycx 代发的) 首先碰到这种期望题,我们套路地设 \(d ...
- BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )
数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了. E(u) = 1 + Σ E(v) / degree(u) 对拍时发现网上2个程序的INF判断和我不一 ...
- 【BZOJ2707】[SDOI2012]走迷宫 Tarjan+拓扑排序+高斯消元+期望
[BZOJ2707][SDOI2012]走迷宫 Description Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,M ...
- BZOJ2707 [SDOI2012]走迷宫 【概率dp + tarjan + 高斯消元】
题目 Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的 ...
随机推荐
- node图片压缩的两员大将
一.ishrink 全局安装 npm i ishrink -g 1.按url方式压缩 本地图片地址 sk -u C:\Users\admin\Desktop\images\img 网络图片地址 sk ...
- Linux yum的实现和配置
使用yum或dnf解决rpm包的依赖关系. YUM:Yellowdog Update Modifier.是rpm的前端程序 作用:解决软件包之间的依赖关系 yum工作原理: yum 服务器存放rpm包 ...
- 在linux上配置Maven环境变量
1.首先下载maven ,这里我使用的是3.8.1 Maven – Download Apache Maven 2.在linux环境中,将maven上传至 /usr/local/目录中 这里我将mav ...
- pyflink的安装和测试
pyflink安装 安装前提:python3.6-3.8 参考:Installation | Apache Flink Python version (3.6, 3.7 or 3.8) is requ ...
- Neural Networks
神经网络能够使用torch.nn包构建神经网络. 现在你已经对autogard有了初步的了解,nn基于autograd来定义模型并进行微分.一个nn.Module包含层,和一个forward(inpu ...
- 广西省行政村边界shp数据/广西省乡镇边界/广西省土地利用分类数据/广西省气象数据/降雨量分布数据/太阳辐射数据
数据下载链接:数据下载链接 广西壮族自治区,地处中国南部,北回归线横贯中部,属亚热带季风气候区.南北以贺州--东兰一线为界,此界以北属中亚热带季风气候区,以南属南亚热带季风气候区. 数据范围:全 ...
- 记录一次ubuntu安装mysql,远程无法登录问题的解决历程
进入ubuntu的mysql配置文件 sudo vim debian.cnf [client] host = localhost user = debian-sys-maint password = ...
- Spring Bean 标签解析
上一篇文章讲到了标签在 parseDefaultElement 方法中进行解析,本篇文章将讲解这部分内容 bean 标签解析 查看 processBeanDefinition 方法,针对各个操作作具体 ...
- day11 Java反射机制
java反射机制 反射是java中的动态机制,它允许我们在程序运行期间再确定类的实例化,方法的调用,属性的调用等,而不是传统意义上的在编码期间确定. 因此,反射可以大大的提高代码的灵活度,但是随之而来 ...
- Kafka Topic Partition Offset 这一长串都是啥?
摘要:Offset 偏移量,是针对于单个partition存在的概念. 本文分享自华为云社区<Kafka Topic Partition Offset 这一长串都是啥?>,作者: gent ...