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表示i的出边指向的店,out[i] 表示i的出边数
如果图是一张DAG,那么直接在反图 上 拓扑排序DP即可
现在有环,那就缩点,环上的用高斯消元
无解的情况:
1、起点走不到终点
2、存在一个联通块,起点能走到他,但这个联通块没有出边,且不是终点所在的联通块
因为此时一旦步入这个联通块将永远走不出去
#include<cmath>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<iostream> #define N 10001
#define M 1000001 using namespace std; int front[N],to[M],nxt[M],tot;
int front_[N],to_[M],nxt_[M],tot_; int dfn[N],low[N],id;
int st[N],top;
bool vis[N]; vector<int>block[N];
int bl[N],cnt;
int num[N]; double out[N];
int in_[N]; bool vis_block[N]; double a[][],dp[N]; queue<int>q; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to_[++tot_]=u; nxt_[tot_]=front_[v]; front_[v]=tot_;
} void tarjan(int x)
{
dfn[x]=low[x]=++id;
st[++top]=x;
vis[x]=true;
for(int i=front[x];i;i=nxt[i])
if(!dfn[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
if(dfn[x]==low[x])
{
cnt++;
while(st[top]!=x)
{
block[cnt].push_back(st[top]);
bl[st[top]]=cnt;
num[st[top]]=block[cnt].size()-;
vis[st[top--]]=false;
}
block[cnt].push_back(x);
bl[x]=cnt;
num[x]=block[cnt].size()-;
vis[st[top--]]=false;
}
} void dfs(int x)
{
vis[x]=vis_block[bl[x]]=true;
for(int i=front[x];i;i=nxt[i])
if(!vis[to[i]]) dfs(to[i]);
} void gauss(int n)
{
int r; double t;
for(int i=;i<n;++i)
{
r=i;
for(int j=i+;j<n;++j)
if(fabs(a[j][i])>fabs(a[r][i])) r=j;
if(r!=i)
for(int j=;j<=n;++j) swap(a[r][j],a[i][j]);
for(int k=i+;k<n;++k)
{
t=a[k][i]/a[i][i];
for(int j=i;j<=n;++j) a[k][j]-=t*a[i][j];
}
}
for(int i=n-;i>=;--i)
{
for(int j=i+;j<n;++j) a[i][n]-=a[i][j]*a[j][n];
a[i][n]/=a[i][i];
}
} int main()
{
int n,m,s,t;
read(n); read(m); read(s); read(t);
int u,v;
for(int i=;i<=m;++i)
{
read(u); read(v);
add(u,v); out[u]++;
}
for(int i=;i<=n;++i)
if(!dfn[i]) tarjan(i);
dfs(s);
if(!vis[t])
{
printf("INF");
return ;
}
for(int i=;i<=n;++i)
for(int j=front[i];j;j=nxt[j])
if(bl[i]!=bl[to[j]]) in_[bl[i]]++;
for(int i=;i<=cnt;++i)
if(vis_block[i] && !in_[i] && i!=bl[t])
{
printf("INF");
return ;
}
for(int i=;i<=n;++i) out[i]=1.0/out[i];
q.push(bl[t]);
int now,siz,x;
while(!q.empty())
{
now=q.front();
q.pop();
memset(a,,sizeof(a));
siz=block[now].size();
for(int i=;i<siz;++i)
{
x=block[now][i];
a[i][i]=;
a[i][siz]=dp[x];
if(x==t) continue;
for(int j=front[x];j;j=nxt[j])
if(bl[to[j]]==now)
{
a[i][siz]+=out[x];
a[i][num[to[j]]]-=out[x];
}
}
gauss(siz);
for(int i=;i<siz;++i)
{
x=block[now][i];
dp[x]=a[i][siz];
for(int j=front_[x];j;j=nxt_[j])
if(bl[to_[j]]!=now)
{
--in_[bl[to_[j]]];
if(!in_[bl[to_[j]]]) q.push(bl[to_[j]]);
dp[to_[j]]+=(dp[x]+)*out[to_[j]];
}
}
}
printf("%.3lf",dp[s]);
}
bzoj千题计划289:bzoj 2707: [SDOI2012]走迷宫的更多相关文章
- 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千题计划300:bzoj4823: [Cqoi2017]老C的方块
http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...
- bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...
- bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)
https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...
- bzoj千题计划209:bzoj1185: [HNOI2007]最小矩形覆盖
http://www.lydsy.com/JudgeOnline/problem.php?id=1185 题解去看它 http://www.cnblogs.com/TheRoadToTheGold/p ...
- bzoj千题计划121:bzoj1033: [ZJOI2008]杀蚂蚁antbuster
http://www.lydsy.com/JudgeOnline/problem.php?id=1033 经半个下午+一个晚上+半个晚上 的 昏天黑地调代码 最终成果: codevs.洛谷.tyvj上 ...
- bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪
http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...
- bzoj千题计划177:bzoj1858: [Scoi2010]序列操作
http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...
随机推荐
- effective c++ 笔记 (9-12)
//---------------------------15/03/29---------------------------- //#9 绝不在构造和析构过程中调头virtual函数 { / ...
- 记一次Java加密加签算法到php的坑
此文为本人原创首发于 http://www.35coder.com/convert_encryption_codes_to_php/. 写代码的经历中,总少不了与外部的程序对接,一旦有这样的事,往往周 ...
- Nginx+IIS分布式部署和负载均衡
1.IIS中部署2个网站 创建2个网站,端口分别为9001.9002 2.下载Nginx 可以进入Nginx官网进行下载,官网地址: http://nginx.org/,需要下载windows版的 3 ...
- PHP学习 函数 function
参数默认值function drink($kind ='tea'){echo 'would you please a cup'.$kind.'<br>';} drink();drink(' ...
- 第二章:蓝色巨人 IBM公司
COBOL(面向商业的通用语言) DEC(数字设备公司)华生实验室 造成失败的原因: 1,没有经营终端消费型产品 2,技术的流失 3.没有在意对手 成为的方法:合并,保守,谨慎 研究员的工作: 1,发 ...
- JS基础(二)数据类型
一.标量类型 1.字符串string类型:字符串需要用定界符包裹.定界符:单引号(‘’),双引号(“”). 2.数字类型:1)整型:所有整数 2)浮点型:所有浮点数 3.boolean类型:返回tru ...
- 关于给C盘扩容以及动态磁盘
2019.4.5 周五 磁盘分为基本磁盘和动态磁盘 基本磁盘转动态磁盘是很容易的 https://jingyan.baidu.com/article/59a015e3a3d504f7948865b1. ...
- CMS垃圾收集器与G1收集器
1.CMS收集器 CMS收集器是一种以获取最短回收停顿时间为目标的收集器.基于“标记-清除”算法实现,它的运作过程如下: 1)初始标记 2)并发标记 3)重新标记 4)并发清除 初始标记.从新标记这两 ...
- Ubuntu忘记MySQL密码重设方法
====================忘了mysql密码,从网上找到的解决方案记录在这里==================== 结束当前正在运行的mysql进程 # /etc/init.d/mys ...
- PHP操作Redis数据库常用方法
Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis支持的数据类型有 Stirng(字符串), Lis ...