Portal --> bzoj2707

Solution

  首先题目有一个十分明显的暗示。。强联通分量。。那肯定就是要tarjan一波咯

  先看看什么情况下会\(INF\),其实就是题目里面讲的两种:

  一种是根本走不到出口,一种是存在一个点,起点能够走到这个点但是这个点走不到出口

  具体判断方式的话分别从起点和出口跑两遍dfs就好了

​  

  对于不是\(INF\)的情况,考虑用dp来算到达每个点的期望步数

  用\(f[i]\)表示\(i\)走到终点的期望步数,\(du[i]\)表示\(i\)点的出度,对于不为出口的点,可以得到式子

\[f[i]=1+\sum f[u]*\frac{1}{du[i]}
\]

  其中\(u\)满足原图中存在一条\((i,u)\)的边

  对于出口\(T\)则有\(f[T]=0\)

  然后每个点的式子是一样的,我们把\(f[i]\)看成未知数,就可以考虑用高斯消元解方程组来解决问题

  然而很尴尬的事情是\(n<=10000\),直接消元愉快爆炸qwq

  

  注意到题目那个给的很奇怪的条件:强联通分量的大小\(<=100\),而对于\(100\)的规模是可以高斯消元的

  所以我们可以将图中的强联通分量分别缩点,然后对每个强联通分量消元

  那对于一个强联通分量里面直接消消不出来的未知数怎么办呢?我们考虑按照一个特定的顺序来处理每个强联通分量,也就是按照缩点后的拓扑序逆序来消,这样可以保证到消到一个强联通分量的时候,里面涉及到的连出去的点的\(f\)值已经被处理出来了,方程数量和包含的未确定的\(f\)值的数量相同,这样在消元的时候就不会出现问题了

​  

  代码大概长这样(小trick在消元的时候两边乘上出度把分母搞掉会比较舒服一点)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#define db double
using namespace std;
const int MAXN=10010;
struct xxx{
int y,nxt;
}a[1000010*2];
int h[MAXN],viscnt[MAXN],vis[MAXN],dfn[MAXN],low[MAXN];
int id[MAXN],belong[MAXN];
int st[MAXN],inst[MAXN],ind[MAXN],outd[MAXN],nind[MAXN],noutd[MAXN];
vector<int>dian[MAXN],na[MAXN],ina[MAXN];
db A[110][110],f[MAXN];
int n,m,tot,T,num,dfn_t,top,S,visT;
void add(int x,int y);
void dfs(int x);
void tarjan(int x);
void prework();
bool check();
void checkdfs1(int x);
void checkdfs2(int x);
void solve();
void solvedfs(int x);
void gauss(int b);
void fill(int b); int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y;
scanf("%d%d%d%d",&n,&m,&S,&T);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
if (x==T) continue;
++ind[y]; ++outd[x];
add(x,y);
}
prework();
solve();
} void prework(){
num=0;
for (int i=1;i<=n;++i)
if (dfn[i]==0) tarjan(i);
int u;
for (int i=1;i<=n;++i){
for (int j=h[i];j!=-1;j=a[j].nxt){
u=a[j].y;
if (belong[i]!=belong[u]){
na[belong[i]].push_back(belong[u]);
ina[belong[u]].push_back(belong[i]);
}
}
}
} void add(int x,int y){
a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;
} void tarjan(int x){
int u;
dfn[x]=++dfn_t; low[x]=dfn[x]; st[++top]=x; inst[x]=true;
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (dfn[u]==0){
tarjan(u);
low[x]=min(low[u],low[x]);
}
else if (inst[u])
low[x]=min(low[x],dfn[u]);
}
if (low[x]==dfn[x]){
++num;
int tmpcnt=0;
do{
u=st[top--]; inst[u]=false;
id[u]=++tmpcnt; nind[num]+=ind[u]; noutd[num]+=outd[u];
belong[u]=num;
dian[num].push_back(u);
}while (u!=x);
}
} void checkdfs1(int x){
int u;
++viscnt[x]; vis[x]=visT;
for (int i=0;i<na[x].size();++i)
if (vis[na[x][i]]!=visT)
checkdfs1(na[x][i]);
} void checkdfs2(int x){
int u;
viscnt[x]+=2; vis[x]=visT;
for (int i=0;i<ina[x].size();++i)
if (vis[ina[x][i]]!=visT)
checkdfs2(ina[x][i]);
} bool check(){
memset(vis,0,sizeof(vis));
++visT; checkdfs1(belong[S]);
++visT; checkdfs2(belong[T]);
for (int i=1;i<=num;++i) if (viscnt[i]==1) return false;
return true;
} void solve(){
if (!check()){printf("INF\n");return;}
++visT;
solvedfs(belong[S]);
printf("%.3lf\n",f[S]);
} void solvedfs(int x){
vis[x]=visT;
for (int i=0;i<na[x].size();++i)
if (vis[na[x][i]]!=visT)
solvedfs(na[x][i]);
gauss(x);
} void fill(int b){
int sz=dian[b].size(),x,u;
memset(A,0,sizeof(A));
for (int i=0;i<sz;++i){
x=dian[b][i];
A[i][sz]=1*outd[x];//all *outd[x];
for (int j=h[x];j!=-1;j=a[j].nxt){
u=a[j].y;
if (belong[u]==b)
A[i][id[u]-1]--;
else
A[i][sz]+=f[u];
}
A[i][i]+=outd[x];
}
} void gauss(int b){
if (b==belong[T]){f[T]=0; return;}
fill(b);
int id,n=dian[b].size();
db tmp;
for (int i=0;i<n;++i){
id=i;
for (int j=i+1;j<n;++j)
if (fabs(A[j][i])>fabs(A[id][i])) id=j;
if (id!=i)
for (int j=0;j<=n;++j) swap(A[id][j],A[i][j]);
for (int j=i+1;j<n;++j){
tmp=A[j][i]/A[i][i];
for (int k=i;k<=n;++k)
A[j][k]-=tmp*A[i][k];
}
}
for (int i=n-1;i>=0;--i){
for (int j=n-1;j>i;--j)
A[i][n]-=A[i][j]*A[j][n];
A[i][n]/=A[i][i];
}
for (int i=0;i<n;++i)
f[dian[b][i]]=A[i][n];
}

【bzoj2707】走迷宫的更多相关文章

  1. [BZOJ2707]走迷宫

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

  2. 【BZOJ2707】[SDOI2012]走迷宫 Tarjan+拓扑排序+高斯消元+期望

    [BZOJ2707][SDOI2012]走迷宫 Description Morenan被困在了一个迷宫里.迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T.可惜的是,M ...

  3. C语言动态走迷宫

    曾经用C语言做过的动态走迷宫程序,先分享代码如下: 代码如下: //头文件 #include<stdio.h> #include<windows.h>//Sleep(500)函 ...

  4. sdut 2449走迷宫【最简单的dfs应用】

    走迷宫 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_ 题目描述 一个由n * m 个格子组成的迷宫,起点是(1, 1), 终点是(n, m) ...

  5. 洛谷P1238 走迷宫

    洛谷1238 走迷宫 题目描述 有一个m*n格的迷宫(表示有m行.n列),其中有可走的也有不可走的,如果用1表示可以走,0表示不可以走,文件读入这m*n个数据和起始点.结束点(起始点和结束点都是用两个 ...

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

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

  7. NYOJ306 走迷宫(dfs+二分搜索)

    题目描写叙述 http://acm.nyist.net/JudgeOnline/problem.php?pid=306 Dr.Kong设计的机器人卡多非常爱玩.它经常偷偷跑出实验室,在某个游乐场玩之不 ...

  8. Problem A: 走迷宫问题

    Problem A: 走迷宫问题Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 9 Solved: 3[Submit][Status][Web Board] ...

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

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

  10. P1238 走迷宫

    原题链接 https://www.luogu.org/problemnew/show/P1238 为了巩固一下刚学习的广搜,练一下迷宫类型的题 不过这道题我用的深搜..... 看问题,我们就知道这道题 ...

随机推荐

  1. Openstack 10 云环境安装

    概述 资源规划 Undercloud Installation Overcloud Installation Trouble Shooting 附录 本指南介绍了如何使用 Red Hat OpenSt ...

  2. while read读取文本内容

    读取文件给 while 循环 方式一: exec <FILE while read line do cmd done 方式二: cat FILE_PATH |while read line do ...

  3. java之接口开发-初级篇-webservice协议

    webservice协议 客户端: 客户端生成使用soapUI生成 外部提供webservice地址,地址后加?wsdl.选择好目录然后生成,放到项目中实现 服务端: web.xml平级目录下创建se ...

  4. 标准版 Eclipse (Eclipse standard 4.3.3) 添加 Tomcat 支持

    步骤1:下载 Eclipse Tomcat 插件最新版:tomcatPluginV33.zip,官网下载最新版:http://www.eclipsetotale.com/tomcatPlugin.ht ...

  5. AngularJS - 路由 routing 基础示例

    AngularJS 路由 routing 能够从页面的一个视图跳转到另外一个视图,对单页面应用来讲是至关重要的.当应用变得越来越复杂时,我们需要一个合理的方式来管理用户在使用过程中看到的界面.Angu ...

  6. Python20-Day01

    简述编译型与解释型语言的区别,且分别列出你知道的哪些语言属于编译型,哪些属于解释 编译型语言是一种以编译器来实现的编程语言,优缺点:执行速度快,调试麻烦 编译型语言:Java,Go,C,C++ 解释性 ...

  7. Yii2 配置request组件解析 json数据

    在基础版本的config目录下 web.php 或者高级版config目录下的main.php中配置 'components' =>[ 'request' => [ 'parsers' = ...

  8. Ubuntu16.04安装oracle-java8-installer

    本篇博客参考 1. 安装默认JRE/JDK 更新 sudo apt-get update 检查是否安装了Java java -version 如果返回The program java can be f ...

  9. 周总结<3>

    经过了一周的学习,我们在html以及C语言方面又有的新的知识点的学习,包括计算机导论也学会了路由器的设置. html 鼠标事件 C 二叉树的遍历代码 计算机导论 路由器的设置 Html案例: < ...

  10. 关于window.open弹出窗口被阻止的问题

    原文:http://blog.csdn.net/fanfanjin/article/details/6858168 在web编程过程中,经常会遇到一些页面需要弹出窗口,但是在服务器端用window.o ...