bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)
Description
Input
Output
|
测试点
|
N
|
M
|
Hint
|
|
[1, 6]
|
<=10
|
<=100
|
|
|
[7, 12]
|
<=200
|
<=10000
|
|
|
[13, 20]
|
<=10000
|
<=1000000
|
保证强连通分量的大小不超过100
|
【思路】
节点u的期望为E(u)=ΣE(v)/deg(u)+1,移项变成deg(u)*E(u)-ΣE(v)=deg(u),而且题目中说到每一个scc中的点数不超过100。我们就可以先划一下scc,将多个节点方程联立,在每个scc中用高斯消元求每个结点的E,O(n^2)。然后再缩点后的图上dfs统计一下就可以啦。
需要注意应该把t的所有出边切掉,因为我们规定E(t)=0。还有就是如果一个scc中有连往scc外的边,我们把常数项加个E
因为我们切了几条边,所以判断得改一下,不能直接判断sccno[S]是否直接到达sccno[T],可以两个点都dfs一遍,如果有sccno[S]不可以到达但sccno[T]可以到达的则为INF,此时出现有一个scc不能到达sccno[T]的情况,于是可以在这个scc中转来转去,即inf。
【代码】
#include<stack>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int N = 1e4+; vector<int> g[][N];
int n,m,S,T,vis[N],deg[N];
double ans[N],mat[][]; int pre[N],sccno[N],id[N],lowlink[N],dfsc,scccnt;
stack<int> st; vector<int> scc[N]; void tarjan(int flag,int u) {
pre[u]=lowlink[u]=++dfsc;
st.push(u); deg[u]=(int)g[flag][u].size();
for(int i=;i<deg[u];i++) {
int v=g[flag][u][i];
if(!pre[v]) {
tarjan(flag,v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
lowlink[u]=min(lowlink[u],pre[v]);
}
if(pre[u]==lowlink[u]) {
++scccnt;
for(;;) {
int x=st.top(); st.pop();
sccno[x]=scccnt;
scc[scccnt].push_back(x);
id[x]=(int)scc[scccnt].size()-;
if(x==u) break;
}
}
} void gause(int x) {
int n=(int)scc[x].size(),i,j,k,r;
for(i=;i<n;i++) {
int u=scc[x][i];
for(j=;j<n;j++) mat[i][j]=;
mat[i][n]=deg[u];
for(j=;j<g[][u].size();j++) {
int v=g[][u][j];
if(sccno[v]==x) {
mat[i][id[v]]--;
} else {
mat[i][n]+=ans[v];
}
}
mat[i][i]+=deg[u];
}
for(i=;i<n;i++) {
r=i;
for(j=i+;j<n;j++)
if(fabs(mat[j][i])>fabs(mat[r][i])) r=j;
if(r!=i) for(j=;j<=n;j++) swap(mat[i][j],mat[r][j]);
for(k=i+;k<n;k++) {
double f=mat[k][i]/mat[i][i];
for(j=i;j<=n;j++) mat[k][j]-=f*mat[i][j];
}
}
for(i=n-;i>=;i--) {
for(j=i+;j<n;j++)
mat[i][n]-=mat[j][n]*mat[i][j];
mat[i][n]/=mat[i][i];
}
for(i=;i<n;i++)
ans[scc[x][i]]=mat[i][n];
} void solve(int u) {
if(u==sccno[T]) {
ans[T]=; return ;
}
for(int i=;i<g[][u].size();i++) {
int v=g[][u][i];
if(!vis[v]) solve(v);
}
vis[u]=;
gause(u);
} int mark[][N];
void dfs(int flag,int u) {
mark[flag][u]=;
for(int i=;i<g[flag][u].size();i++) {
int v=g[flag][u][i];
if(!mark[flag][v]) dfs(flag,v);
}
}
int main() {
scanf("%d%d%d%d",&n,&m,&S,&T);
S--,T--;
int u,v;
for(int i=;i<m;i++) {
scanf("%d%d",&u,&v);
u-- , v--;
if(u==T) continue;
g[][u].push_back(v);
}
for(int i=;i<n;i++)
if(!pre[i]) tarjan(,i);
for(int i=;i<n;i++) {
for(int j=;j<g[][i].size();j++) {
int v=g[][i][j];
if(sccno[i]!=sccno[v]) {
g[][sccno[i]].push_back(sccno[v]);
g[][sccno[v]].push_back(sccno[i]);
}
}
}
dfs(,sccno[S]); dfs(,sccno[T]);
for(int i=;i<=scccnt;i++)
if(mark[][i]&&!mark[][i]) {
puts("INF"); return ;
}
solve(sccno[S]);
printf("%.3f",ans[S]);
return ;
}
PS:
这个题=-= 好神啊0_0
其实第一眼蒟蒻是想dfs来着,但是有圈啊……有圈啊……有圈啊……
bzoj 2707 [SDOI2012]走迷宫(SCC+高斯消元)的更多相关文章
- BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )
数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了. E(u) = 1 + Σ E(v) / degree(u) 对拍时发现网上2个程序的INF判断和我不一 ...
- BZOJ 2707: [SDOI2012]走迷宫 拓扑+高斯消元+期望概率dp+Tarjan
先Tarjan缩点 强连通分量里用高斯消元外面直接转移 注意删掉终点出边和拓扑 #include<cstdio> #include<cstring> #include<a ...
- 洛谷 P6030 - [SDOI2012]走迷宫(高斯消元+SCC 缩点)
题面传送门 之所以写个题解是因为题解区大部分题解的做法都有 bug(u1s1 周六上午在讨论区里连发两个 hack 的是我,由于我被禁言才让 ycx 代发的) 首先碰到这种期望题,我们套路地设 \(d ...
- BZOJ 2707: [SDOI2012]走迷宫 [高斯消元 scc缩点]
2707: [SDOI2012]走迷宫 题意:求s走到t期望步数,\(n \le 10^4\),保证\(|SCC| \le 100\) 求scc缩点,每个scc高斯消元,scc之间直接DP 注意每次清 ...
- BZOJ.2707.[SDOI2012]走迷宫(期望 Tarjan 高斯消元)
题目链接 一个点到达终点的期望步数 \(E_i=\sum_{(i,j)\in G}\frac{E_j+1}{out[i]}\),\(out[i]\)为点\(i\)的出度. 那么对于一个DAG可以直接在 ...
- 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 ...
- BZOJ 3143 游走(贪心+期望+高斯消元)
一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分 ...
- BZOJ 3143 游走 | 数学期望 高斯消元
啊 我永远喜欢期望题 BZOJ 3143 游走 题意 有一个n个点m条边的无向联通图,每条边按1~m编号,从1号点出发,每次随机选择与当前点相连的一条边,走到这条边的另一个端点,一旦走到n号节点就停下 ...
- BZOJ.3143.[HNOI2013]游走(概率 期望 高斯消元)
题目链接 参考 远航之曲 把走每条边的概率乘上分配的标号就是它的期望,所以我们肯定是把大的编号分配给走的概率最低的边. 我们只要计算出经过所有点的概率,就可以得出经过一条边(\(u->v\))的 ...
随机推荐
- func_get_args的使用
func_get_args是获取方法中参数的数组,返回的是一个数组,与func_num_args搭配使用:func_num_args一般写在方法中,用于计数:使用方法如下:function foo($ ...
- HTML meta viewport属性说明
什么是Viewport 手机浏览器是把页面放在一个虚拟的“窗口”(viewport)中,通常这个虚拟的“窗口”(viewport)比屏幕宽,这样就不用把每个网页挤 到很小的窗口中(这样会破坏没有针对手 ...
- PythonCrawl自学日志(4)
2016年9月22日10:34:02一.Selector1.如何构建(1)text构建: body = '<html><body><span>good</sp ...
- python 调用第三方库压缩png或者转换成webp
因为工作需要去研究了下png的压缩,发现转换成webp可以小很多,但是webp在手机上的解码速度比png的解码速度慢很多.出于进几年手机设备的处理器的性能也不错了,所以准备两套方案. 在网上搜索了一些 ...
- UIViewCotroller 的生命周期函数
Viewcontroller 的所有生命周期函数 重写时 一定要先写 父类 方法 就是(super +生命周期函数) LoadView ViewDidLoad ViewDidUnload: 在iOS ...
- struts2用了哪几种模式
代理模式 责任连模式 ActionVacation 迭代模式
- 静态页面参数传递&回调函数写法&快速排序的实现方法
相信很多人都有一种陋习,就是收藏的文章,几乎从来都没有回过头来仔细看过.这次借着这次活动的机会,在<无懈可击的web设计>一书的学习过程中,穿插着讲自己曾经收藏过的,现在觉得还有价值的文章 ...
- C#变成数据导入Excel和导出Excel
excel 基础 •整个excel 表格叫工作表:workbook:工作表包含的叫页:sheet:行:row:单元格:cell. •excel 中的电话号码问题,看起来像数字的字符串以半角单引号开头就 ...
- hdu 3718
一个二分图最大匹配的题: 匈牙利算法不熟: 建了个模,用最小费用最大流解决了 #include <iostream> #include <cstring> #define IN ...
- 如何登录mysql? cmd怎么连接mysql数据库
Mysql开源数据库,任何人都可以下载安装使用.那么安装好的mysql如何登陆连接mysql数据库呢? 连接mysql数据库的几种方法 一 Mysql命令行连接 一般对于刚刚安装好的mysql,如果勾 ...