Description
Morenan被困在了一个迷宫里。迷宫可以视为N个点M条边的有向图,其中Morenan处于起点S,迷宫的终点设为T。可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的有向边,到达另一个点。这样,Morenan走的步数可能很长,也可能是无限,更可能到不了终点。若到不了终点,则步数视为无穷大。但你必须想方设法求出Morenan所走步数的期望值。
N<=10000
M<=1000000
保证强连通分量的大小不超过100
另外,均匀分布着40%的数据,图中没有环,也没有自环
Solution
抛开环不谈,若给定的图是dag那么递推一下就好了
现在加上环的限制,先缩点
发现环很小,那么环里面的就高斯消元,环与环之间把已经求出来的变量当成常数套进去消元就行了
码力十分不足,我大概是zhizhang选手写了2h+
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
#define fill(x,t) memset(x,t,sizeof(x))
const int N=40005;
const int E=2000005;
struct edge {int x,y,next;} e[E];
std:: stack <int> stack;
// std:: vector <int> rec[N];
double a[205][205],ans[N];
int in[N],_in[N],out[N],d[N];
int dfn[N],low[N],bel[N];
int queue[N],head=1,tail=0;
int ls[N],edCnt,tot;
int rec[N][205],pos[N];
bool vis[N],flag=false;
void addEdge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]};
ls[x]=edCnt; in[y]++; out[x]+=(x!=y); d[x]++;
}
void dfs(int now) {
dfn[now]=low[now]=++tot;
stack.push(now); vis[now]=1;
for (int i=ls[now];i;i=e[i].next) {
if (!dfn[e[i].y]) {
dfs(e[i].y);
low[now]=std:: min(low[now],low[e[i].y]);
} else if (vis[e[i].y]) {
low[now]=std:: min(low[now],dfn[e[i].y]);
}
}
if (low[now]==dfn[now]) {
bel[0]++;
for (int tmp=0;tmp!=now;) {
tmp=stack.top(); stack.pop();
bel[tmp]=bel[0];
vis[tmp]=0;
rec[bel[0]][++rec[bel[0]][0]]=tmp;
}
}
}
void gauss(int n) {
rep(i,1,n) {
int l=i;
rep(j,i+1,n) if (fabs(a[j][i])>fabs(a[l][i])) l=j;
if (l!=i) std:: swap(a[i],a[l]);
double tmp=a[i][i];
rep(j,1,n+1) a[i][j]/=tmp;
rep(j,1,n) {
if (i!=j&&a[j][i]) {
tmp=a[j][i];
rep(k,1,n+1) a[j][k]-=a[i][k]*tmp;
}
}
}
}
void calc(int x) {
fill(a,0); int size=rec[x][0];
rep(i,1,size) pos[rec[x][i]]=i;
rep(ti,1,size) {
int now=rec[x][ti];
if (!d[now]) return ;
for (int i=ls[now];i;i=e[i].next) {
if (bel[e[i].x]==bel[e[i].y]) {
a[pos[now]][pos[e[i].y]]+=1.0/(double)d[now];
} else {
a[pos[now]][size+1]-=1.0*ans[e[i].y]/(double)d[now];
}
}
a[pos[now]][size+1]-=1.0;
a[pos[now]][pos[now]]+=-1.0;
}
gauss(size);
rep(i,1,size) ans[rec[x][i]]=a[i][size+1];
}
void top_sort(int n) {
memcpy(_in,in,sizeof(in));
rep(i,1,n) {
if (in[i]==0) {
queue[++tail]=i;
}
}
while (head<=tail) {
int now=queue[head++];
rep(j,1,rec[now][0]) {
for (int i=ls[rec[now][j]];i;i=e[i].next) {
if (bel[e[i].x]==bel[e[i].y]) continue;
if (!(--in[bel[e[i].y]])) {
queue[++tail]=bel[e[i].y];
}
}
}
}
memcpy(in,_in,sizeof(in));
drp(ti,n,1) {
int now=queue[ti] ;
calc(now);
}
}
void tarjan(int n,int st,int ed) {
dfs(st);
rep(i,1,n) {
if (i!=ed&&dfn[i]&&!out[i]) {
puts("INF");
flag=true;
return ;
}
if (i==ed&&!dfn[i]) {
puts("INF");
flag=true;
return ;
}
}
fill(in,0); fill(out,0);
rep(i,1,edCnt) {
if (bel[e[i].x]!=bel[e[i].y]&&bel[e[i].x]&&bel[e[i].y]) {
in[bel[e[i].y]]++;
out[bel[e[i].x]]++;
}
}
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n,m,st,ed; scanf("%d%d%d%d",&n,&m,&st,&ed);
rep(i,1,m) {
int x,y; scanf("%d%d",&x,&y);
if (x!=ed) addEdge(x,y);
}
tarjan(n,st,ed);
if (flag) return 0;
top_sort(bel[0]);
rep(i,1,n)
printf("%.3lf\n", ans[i]);
return 0;
}