╰( ̄▽ ̄)╭

Morenan 被困在了一个迷宫里。

迷宫可以视为 N 个点 M 条边的有向图,其中 Morena n处于起点 S , 迷宫的终点设为 T 。

可惜的是 , Morenan 非常的脑小 , 他只会从一个点出发随机沿着一条从该点出发的有向边 , 到达另一个点 。

这样 , Morenan 走的步数可能很长 , 也可能是无限,更可能到不了终点。

若到不了终点,则步数视为无穷大。

但你必须想方设法求出 Morenan 所走步数的期望值。

(⊙ ▽ ⊙)

一开始看着道题,就觉得是tarjan缩点后,转化成DAG上的问题。

当原图是DAG时

设fi表示第i个点走到终点的距离。

容易有fi=∑j∈next(i)1|next(i)|∗(fj+1),

其中next(i)是i的后继集合。

很容易使用拓扑排序来完成动态规划。

当原图是一般的有向图时

利用tarjan算法可以把图中的强连通分量找出来。

对于任意一个强连通分量,我们利用高斯消元来求解出强连通分量中的每个点的f值。

套上拓扑排序,就能够解决。


时间复杂度为O(n∗L3),其中L为最大强连通分量的大小。

实际时间复杂度则远远不到。

( ̄~ ̄)

高斯(gauss)消元:

1.目标

对n条n元一次方程求解。

2.步骤

首先:

把某条方程的第一个元的系数化为一,利用它可以消去其他方程的第一元。

以此类推,可以消去第二个元、第三个元……

最后,会只剩下一条只关于最后一元的方程,实际上就是这一元的根。

然后:

得出最后一元的根后,就可以代入先前的方程。

于是可以算出所有元的根。

(⊙v⊙)

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
#define ll long long
using namespace std;
const char* fin="jzoj2758.in";
const char* fout="jzoj2758.out";
const int Inf=0x7fffffff;
const int maxn=20007,maxm=2000007,maxk=107;
int n,m,St,En,i,j,k,N,ti;
int fi[maxn],ne[maxm],la[maxm],tot;
int Fi[maxn],Ne[maxm],La[maxm],Tot;
int dfn[maxn],low[maxn],num,st[maxn],be[maxn];
bool bz[maxn],End;
int inf[maxn];
int az[maxn];
int ha[maxn][maxk],ru[maxn],id[maxn],tow[maxn];
double f[maxn],gs[maxk][maxk];
int b[maxn],head,tail;
void add_line(int a,int b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
void Add_line(int a,int b){
Tot++;
Ne[Tot]=Fi[a];
La[Tot]=b;
Fi[a]=Tot;
}
void tarjan(int v){
int i,j,k;
dfn[v]=low[v]=++num;
bz[st[j=++st[0]]=v]=true;
for (k=fi[v];k;k=ne[k])
if (!dfn[la[k]]){
tarjan(la[k]);
low[v]=min(low[v],low[la[k]]);
}else if (bz[la[k]]) low[v]=min(low[la[k]],low[v]);
if (low[v]==dfn[v]){
N++;
be[N]=0;
while (st[0]>=j){
ha[N][++ha[N][0]]=st[st[0]];
be[st[st[0]]]=N;
bz[st[st[0]--]]=false;
}
}
}
double ABS(double x){
return x>0?x:-x;
}
void add(int v){
b[++tail]=v;
}
void count(int v,int n){
int i,j,k,l;
double tmp,tmd;
ti++;
for (i=1;i<=n-1;i++){
for (j=1;j<n;j++){
if (az[j]<ti && (gs[j][i]>10e-13 || gs[j][i]<-10e-13)){
az[j]=ti;
tow[i]=j;
tmp=1.0/gs[j][i];
for (k=1;k<=n;k++) gs[j][k]*=tmp;
for (k=1;k<n;k++){
if (k==j) continue;
tmd=gs[k][i];
for (l=1;l<=n;l++)
gs[k][l]-=tmd*gs[j][l];
}
break;
}
}
}
for (i=n-1;i>=1;i--){
f[ha[v][tow[i]]]=-gs[tow[i]][n];
for (j=1;j<=n-1;j++){
gs[j][n]-=gs[j][i]*gs[tow[i]][n];
}
}
}
void work(int v){
int i,j,k;
for (i=1;i<=ha[v][0];i++) id[ha[v][i]]=i;
for (i=1;i<=ha[v][0];i++){
for (j=1;j<=ha[v][0]+1;j++) gs[i][j]=0;
j=0;
for (k=Fi[ha[v][i]];k;k=Ne[k]){
gs[i][ha[v][0]+1]+=1;
gs[i][i]-=1;
if (f[La[k]]>10e-7 || La[k]==En) gs[i][ha[v][0]+1]+=f[La[k]];
else gs[i][id[La[k]]]+=1;
}
}
count(v,ha[v][0]+1);
}
void update(int v){
int i,j,k;
for (i=1;i<=ha[v][0];i++)
for (k=fi[ha[v][i]];k;k=ne[k]){
inf[be[la[k]]]=max(inf[be[la[k]]],inf[v]);
if (!--ru[be[la[k]]]) add(be[la[k]]);
}
}
void topsort(){
int i,j,k;
head=tail=0;
memset(f,0,sizeof(f));
f[En]=0;
for (i=n+1;i<=N;i++)
if (!ru[i]){
add(i);
}
while (head++<tail){
if (be[En]==b[head]) inf[b[head]]=1;
if (inf[b[head]]==0) inf[b[head]]=2;
if (inf[b[head]]==1 && b[head]!=be[En]) work(b[head]);
update(b[head]);
}
}
int main(){
scanf("%d%d%d%d",&n,&m,&St,&En);
N=n;
for (i=1;i<=m;i++){
scanf("%d%d",&j,&k);
if (j!=En){
Add_line(j,k);
add_line(k,j);
}
}
for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (i=1;i<=n;i++)
for (k=fi[i];k;k=ne[k])
if (be[la[k]]!=be[i]) ru[be[la[k]]]++;
topsort();
//printf("%3.lf",f[St]);
if (inf[be[St]]!=1) printf("INF");
else printf("%.3lf",f[St]);
return 0;
}

【JZOJ2758】【SDOI2012】走迷宫(labyrinth)的更多相关文章

  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. 【BZOJ2707】[SDOI2012]走迷宫 Tarjan+拓扑排序+高斯消元+期望

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

  4. SDOI2012 走迷宫

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

  5. bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)

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

  6. BZOJ2707 [SDOI2012]走迷宫 【概率dp + tarjan + 高斯消元】

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

  7. [SDOI2012]走迷宫 (强连通分量缩点,动态规划,高斯消元)

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

  8. bzoj2702[SDOI2012]走迷宫

    题意:给你一个有向图,点数10000,边数1000000,SCC大小不超过100(按数据范围的写法只有第三部分数据满足这个条件,不过第二部分数据并没有出现大小大于100个点的SCC,我是用数组大小为1 ...

  9. BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)

    题目链接 一个点到达终点的期望步数 \(E_i=\sum_{(i,j)\in G}\frac{E_j+1}{out[i]}\),\(out[i]\)为点\(i\)的出度. 那么对于一个DAG可以直接在 ...

随机推荐

  1. ssh小知识

    1.查看系统在线用户 [root@testdb ~]# w 14:30:26 up 38 days, 21:22, 3 users, load average: 0.00, 0.01, 0.05USE ...

  2. SQL Server代码如何快速格式化,sqlserver代码

    在SQL Server中我们经常需要编写各种SQL脚本,例如存储过程和函数等,由于在编写过程中,经常会进行调整,有些关键字我们用的大写,有的我们用的小写,有的后面结束用:分割有的又没有.对于有强迫症的 ...

  3. Java面试总结-基础篇1

    java多线程-- 自旋锁,偏向锁 好处:可以举Servlet和CGI的对比用户线程和守护线程的区别:用户线程结束后JVM会退出,然后守护线程才会终止(比如垃圾回收线程),如何在java中创建守护线程 ...

  4. XML 映射文件

    MyBatis 的真正强大在于它的映射语句,这是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% ...

  5. npm 安装删除模块

    npm安装模块 [npm install xxx]利用 npm 安装xxx模块到当前命令行所在目录: [npm install -g xxx]利用npm安装全局模块xxx: 本地安装时将模块写入pac ...

  6. HNOI 2019 多边形

    HNOI 2019 多边形 题意 小 R 与小 W 在玩游戏. 他们有一个边数为\(n\)的凸多边形,其顶点沿逆时针方向标号依次为\(1,2,3...n\).最开始凸多边形中有\(n\)条线段,即多边 ...

  7. 关于在静态html中实现语言切换的思路与实现

    在项目中只用到了三种语言:英文.中文简体.中文繁体.所以我首先想到了最笨的方法:1.直接将三种语言写在html中,显示当前设置的语言隐藏其它两种来实现.2.使用css伪元素的content:attr( ...

  8. bzoj 1053 [HAOI2007]反素数ant——关于质数的dfs / 打表

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1053 写了个打表程序. #include<iostream> #include& ...

  9. css上下左右居中

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 如何在linux中部署mongodb并设置连接认证

    在windows上给mongodb设置连接认证权限:mongodb默认是不认证的,默认没有账号,现在就讲讲怎么设置账户和密码 1.首先进入C:\mongodb\bin下面双击运行mongo.exe启动 ...