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. 第七章移动互联网与移动IP

    第七章移动互联网与移动IP 本章延续前几章节,对该章节内容进行归纳总结. 文章中的Why表示产生的背景,也就是说为什么会产生该技术,What表示该技术是什么,How表示该技术是如何使用的.以下将用字母 ...

  2. python模块的作用和说明

    Python模块 如果你从Python解释器退出并再次进入,之前的定义(函数和变量)都会丢失.因此,如果你想编写一个稍长些的程序,最好使用文本编辑器为解释器准备输入并将该文件作为输入运行.这被称作编写 ...

  3. NO--10今天带大家回忆回忆“闭包”吧!

    对于‘闭包,我相信很多人都掉进过这个坑里,也相信很多人没能详细的理解这个问题,今天带大家再次走进闭包: 写这篇文章时的心情是十分忐忑的,因为对于我们今天的主角:闭包,很多小伙伴都写过关于它的文章,相信 ...

  4. Javascript深入__proto__和prototype的区别和联系

    有一个一个装逼的同事,写了一段代码 function a(){} a.__proto__.__proto__.__proto__ 然后问我,下面这个玩意a.__proto__.__proto__.__ ...

  5. Java基础知识:Java实现Map集合二级联动2

    2. 定义获取省份的方法,创建一个Map集合,将上一步得到的映射集合赋值给它,使用Map集合的keySet()方法获取该集合中的所有键对象组成的Set 集合,即为省分集合,创建一个Object型一维数 ...

  6. 在Office 365 的如何给管理员赋予查看所有人邮箱的权限的Powershell

    连接至Office365 的Powershell Get-MsolUser -UserPrincipalName admin@***.partner.onmschina.cn //Get-MsolUs ...

  7. 2019CSUST集训队选拔赛题解(一)

    来自ppq的毒瘤线段树 Sneakers   Description 有一天喜欢买鞋的ppq和小伙伴来到了某一家球鞋店,球鞋店有n种球鞋,价格分别为ai,ppq在鞋店兜兜转转,发现鞋店老板会偶尔将某段 ...

  8. Paper Reading - Show and Tell: A Neural Image Caption Generator ( CVPR 2015 )

    Link of the Paper: https://arxiv.org/abs/1411.4555 Main Points: A generative model ( NIC, GoogLeNet ...

  9. Android:有关下拉菜单导航的学习(供自己参考)

    Android:有关==下拉菜单导航==的学习 因为先前的学习都没想着记录自己的学习历程,所以该博客才那么迟才开始写. 内容: ==下拉菜单导航== 学习网站:android Spinner控件详解 ...

  10. “我爱淘”第二冲刺阶段Scrum站立会议6

    完成任务: 完成学院分类的点击查看书籍功能,可以点击书的条目查看书的详细信息. 计划任务: 将书的详细信息进行完善,并且可以点击收藏以及已预订等功能. 遇到问题: 分类功能,根据不同学院,自动将数据库 ...