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]走迷宫的更多相关文章

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

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

  2. BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]

    2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...

  3. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

  4. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  5. bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...

  6. bzoj千题计划209:bzoj1185: [HNOI2007]最小矩形覆盖

    http://www.lydsy.com/JudgeOnline/problem.php?id=1185 题解去看它 http://www.cnblogs.com/TheRoadToTheGold/p ...

  7. bzoj千题计划121:bzoj1033: [ZJOI2008]杀蚂蚁antbuster

    http://www.lydsy.com/JudgeOnline/problem.php?id=1033 经半个下午+一个晚上+半个晚上 的 昏天黑地调代码 最终成果: codevs.洛谷.tyvj上 ...

  8. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  9. bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...

随机推荐

  1. (2)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- .NetCore启动配置 和 .NetCoreWebApi

    什么是.Net Core?.Net Core是微软开发的另外一个可以跨Linux.Windows.mac等平台的.Net.Net Core相关知识看文章地步dotnet dllname.dll 运行P ...

  2. OpenCV操作像素

    在了解了图像的基础知识和OpenCV的基础知识和操作以后,接下来我们要做的就对像素进行操作,我们知道了图像的本质就是一个矩阵,那么一个矩阵中存储了那么多的像素,我们如何来操作呢?下面通过几个例子来看看 ...

  3. docker教程——docker镜像打包上传

    在开始使用URLOS进行docker应用开发之前,我们先来了解一下docker镜像的打包方法.首先,安装URLOS,安装完成之后,docker也随之安装到了主机里.执行以下命令安装URLOS: cur ...

  4. 微软职位内部推荐-Senior Software Engineer - Front End

    微软近期Open的职位: SharePoint is a multi-billion dollar enterprise business that has grown from an on-prem ...

  5. PAT甲题题解-1114. Family Property (25)-(并查集模板题)

    题意:给出每个人的家庭成员信息和自己的房产个数与房产总面积,让你统计出每个家庭的人口数.人均房产个数和人均房产面积.第一行输出家庭个数,随后每行输出家庭成员的最小编号.家庭人口数.人均房产个数.人均房 ...

  6. 一张图理解Git

    更详细的git介绍:Git操作指南

  7. Github与SmartGit使用说明与建议

    当使用github做协同的时候,我们常常需要在客户端安装相应的软件,SmartGit就是一款非常出色的软件,不过是要付费的,我们可以使用non-commercial版本. Download: http ...

  8. python进阶:Python进程、线程、队列、生产者/消费者模式、协程

    一.进程和线程的基本理解 1.进程 程序是由指令和数据组成的,编译为二进制格式后在硬盘存储,程序启动的过程是将二进制数据加载进内存,这个启动了的程序就称作进程(可简单理解为进行中的程序).例如打开一个 ...

  9. 【bzoj5073】[Lydsy1710月赛]小A的咒语 后缀数组+倍增RMQ+贪心+dp

    题目描述 给出 $A$ 串和 $B$ 串,从 $A$ 串中选出至多 $x$ 个互不重合的段,使得它们按照原顺序拼接后能够得到 $B$ 串.求是否可行.多组数据. $T\le 10$ ,$|A|,|B| ...

  10. native2ascii -reverse -encoding UTF-8 validation_msg.properties > validation_msg_src.properties

    native2ascii -reverse -encoding UTF-8 validation_msg.properties > validation_msg_src.properties