数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了.

E(u) = 1 + Σ E(v) / degree(u)

对拍时发现网上2个程序的INF判断和我不一样(他们2个的INF判断也不一样).....然而都A掉了....我觉得应该是他们写错了,我的做法应该没错的(正反2遍dfs,GDOI2015day1t1大冒险)(求打脸

------------------------------------------------------------------------

#include<cmath>
#include<stack>
#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int maxn = 10009;
const int maxb = 209;
const double eps = 1e-8;
 
int N, S, T, deg[maxn];
int dfn[maxn], low[maxn], sz[maxn], CK;
int scc[maxn], Scc[maxn][maxb], Id[maxn], n;
bool F[maxn];
stack<int> stk;
double ans[maxn], mat[maxb][maxb];
 
inline void Min(int &x, int t) {
if(t < x) x = t;
}
 
struct edge {
int t;
edge* n;
} E[5000000], *pt = E;
 
struct G {
edge* H[maxn];
bool vis[maxn];
inline void AddEdge(int u, int v) {
pt->t = v, pt->n = H[u], H[u] = pt++;
}
void dfs(int x) {
vis[x] = true;
for(edge* e = H[x]; e; e = e->n)
if(!vis[e->t]) dfs(e->t);
}
void DFS(int x) {
memset(vis, 0, sizeof vis);
dfs(x);
}
} g[3];
 
void tarjan(int x) {
dfn[x] = low[x] = ++CK;
stk.push(x);
for(edge* e = g[0].H[x]; e; e = e->n) if(!dfn[e->t]) {
tarjan(e->t);
Min(low[x], low[e->t]);
} else if(!~scc[e->t])
Min(low[x], dfn[e->t]);
if(dfn[x] == low[x]) {
int t;
do {
t = stk.top(); stk.pop();
scc[t] = n;
Id[t] = sz[n];
Scc[n][sz[n]++] = t;
} while(t != x);
n++;
}
}
 
void Init() {
int m, u, v;
scanf("%d%d%d%d", &N, &m, &S, &T);
S--, T--;
memset(deg, 0, sizeof deg);
while(m--) {
scanf("%d%d", &u, &v);
u--, v--;
if(u == T) continue;
g[0].AddEdge(u, v);
deg[u]++;
}
}
 
void Solve(int x) {
if(x == scc[T]) {
ans[T] = 0;
return;
}
for(int i = 0; i < sz[x]; i++) {
for(int j = 0; j < sz[x]; j++) mat[i][j] = 0;
mat[i][sz[x]] = deg[Scc[x][i]];
for(edge* e = g[0].H[Scc[x][i]]; e; e = e->n)
if(scc[e->t] == x) {
mat[i][Id[e->t]]--;
} else if(e->t != T)
mat[i][sz[x]] += ans[e->t];
mat[i][i] += deg[Scc[x][i]];
}
for(int i = 0, r; i < sz[x]; i++) {
r = i;
for(int j = i; ++j < sz[x]; )
if(fabs(mat[j][i]) > fabs(mat[r][i])) r = j;
if(r != i) {
for(int j = 0; j <= sz[x]; j++)
swap(mat[i][j], mat[r][j]);
}
for(int j = i; ++j < sz[x]; ) {
double t = mat[j][i] / mat[i][i];
for(int k = i; k <= sz[x]; k++)
mat[j][k] -= t * mat[i][k];
}
}
for(int i = sz[x]; i--; ) {
for(int j = i; ++j < sz[x]; )
mat[i][sz[x]] -= mat[j][sz[x]] * mat[i][j];
mat[i][sz[x]] /= mat[i][i];
}
for(int i = 0; i < sz[x]; i++)
ans[Scc[x][i]] = mat[i][sz[x]];
}
 
void dfs(int x) {
for(edge* e = g[1].H[x]; e; e = e->n)
if(!F[e->t]) dfs(e->t);
F[x] = true;
Solve(x);
}
 
void Work() {
if(S == T) {
puts("0.000");
return;
}
memset(dfn, 0, sizeof dfn);
memset(scc, -1, sizeof scc);
memset(sz, 0, sizeof sz);
CK = n = 0;
for(int i = 0; i < N; i++)
if(!dfn[i]) tarjan(i);
for(int i = 0; i < N; i++)
for(edge* e = g[0].H[i]; e; e = e->n) if(scc[i] != scc[e->t]) {
g[1].AddEdge(scc[i], scc[e->t]);
g[2].AddEdge(scc[e->t], scc[i]);
}
g[1].DFS(scc[S]), g[2].DFS(scc[T]);
for(int i = 0; i < n; i++) if(g[1].vis[i] && !g[2].vis[i]) {
puts("INF"); return;
}
memset(F, 0, sizeof F);
dfs(scc[S]);
printf("%.3lf\n", ans[S]);
}
 
int main() {
Init();
Work();
return 0;
}

------------------------------------------------------------------------

2707: [SDOI2012]走迷宫

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 372  Solved: 149
[Submit][Status][Discuss]

Description

Morenan被困在了一个迷宫里。迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T。可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的有向边,到达另一个点。这样,Morenan走的步数可能很长,也可能是无限,更可能到不了终点。若到不了终点,则步数视为无穷大。但你必须想方设法求出Morenan所走步数的期望值。

Input

第1行4个整数,N,M,S,T
第[2, M+1]行每行两个整数o1, o2,表示有一条从o1到o2的边。

Output

一个浮点数,保留小数点3位,为步数的期望值。若期望值为无穷大,则输出"INF"。
【样例输入1】
6 6 1 6
1 2
1 3
2 4
3 5
4 6
5 6
【样例输出1】
3.000
【样例输入2】
9 12 1 9
1 2
2 3
3 1
3 4
3 7
4 5
5 6
6 4
6 7
7 8
8 9
9 7
【样例输出2】
9.500
【样例输入3】
2 0 1 2
【样例输出3】
INF
【数据范围】
测试点
N
M
Hint
[1, 6]
<=10
<=100
 
[7, 12]
<=200
<=10000
 
[13, 20]
<=10000
<=1000000
保证强连通分量的大小不超过100
 
 
另外,均匀分布着40%的数据,图中没有环,也没有自环

Sample Input

Sample Output

HINT

Source

BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )的更多相关文章

  1. BZOJ 2707: [SDOI2012]走迷宫 拓扑+高斯消元+期望概率dp+Tarjan

    先Tarjan缩点 强连通分量里用高斯消元外面直接转移 注意删掉终点出边和拓扑 #include<cstdio> #include<cstring> #include<a ...

  2. 洛谷 P6030 - [SDOI2012]走迷宫(高斯消元+SCC 缩点)

    题面传送门 之所以写个题解是因为题解区大部分题解的做法都有 bug(u1s1 周六上午在讨论区里连发两个 hack 的是我,由于我被禁言才让 ycx 代发的) 首先碰到这种期望题,我们套路地设 \(d ...

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

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

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

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

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

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

  6. 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 ...

  7. BZOJ 3143 游走(贪心+期望+高斯消元)

    一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...

  8. BZOJ 3143 游走 | 数学期望 高斯消元

    啊 我永远喜欢期望题 BZOJ 3143 游走 题意 有一个n个点m条边的无向联通图,每条边按1~m编号,从1号点出发,每次随机选择与当前点相连的一条边,走到这条边的另一个端点,一旦走到n号节点就停下 ...

  9. BZOJ.4820.[SDOI2017]硬币游戏(思路 高斯消元 哈希/AC自动机/KMP)

    BZOJ 洛谷 建出AC自动机,每个点向两个儿子连边,可以得到一张有向图.参照 [SDOI2012]走迷宫 可以得到一个\(Tarjan\)+高斯消元的\(O((nm)^3)\)的做法.(理论有\(6 ...

随机推荐

  1. 字符串对比.net String.EndsWith方法 (String)

    string str="web/abc.aspx"; if(str.EndsWith("abc.aspx")) { 此方法将 value 与位于此实例末尾.与 ...

  2. PHP自学4——通过函数将数组数据输出到html的Table标签中(使用函数的例子)

    这一节其实说实话并没有什么干货,不过为了防止PO主的懒癌的复发,还是坚持放一点东西,即使是内容和长度都令人发指.这一节通过一个函数来实现将数组中的内容输出html的Table标签当中显示. 函数文件— ...

  3. uva11029 - Leading and Trailing

    题目: 求n的k次方,然后将答案用前三位和最后三位表示. Sample Input 2 123456 1 123456 2 Sample Output 123...456 152...936 分析: ...

  4. (七)Android中AIDL的应用与理解

    一.跨应用启动Service Intent serviceIntent=new Intent();serviceIntent.setComponent(new ComponentName(" ...

  5. 使用 Oracle Sql plus的一点经验

    1    当你输入的语句有错误的时候,不用重新输入语句,直接输入ed就会出现一个文本文档显示之前输入的语句,这样你可以在文本文档里面修改语句,最后点保存. 2 三个set:设置每行显示的记录长度:SE ...

  6. NHibernate各种数据库连接参数文件配置方法说明

    //NHibernate各种数据库连接参数文件配置方法说明 //配置文件Config/Hibernate.cfg.xml内容如下所示: <?xml version="1.0" ...

  7. Hadoop数据操作系统YARN全解析

    “ Hadoop 2.0引入YARN,大大提高了集群的资源利用率并降低了集群管理成本.其在异构集群中是怎样应用的?Hulu又有哪些成功实践可以分享? 为了能够对集群中的资源进行统一管理和调度,Hado ...

  8. Linux定时任务Crontab命令详解

    linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者自己也可以设置计划任务,所以, ...

  9. Python爬虫实战(2):爬取京东商品列表

    1,引言 在上一篇<Python爬虫实战:爬取Drupal论坛帖子列表>,爬取了一个用Drupal做的论坛,是静态页面,抓取比较容易,即使直接解析html源文件都可以抓取到需要的内容.相反 ...

  10. Python学习笔记(三)Python的list和tuple

    list list类似其他语言中的数组,是一种有序的集合,可以随时添加和删除其中的元素. 使用len()函数可以获得list元素的个数. list的索引从0开始,当超出范围时会报IndexError错 ...