题目大意
Morenan 被困在了一个迷宫里。迷宫可以视为 N 个点 M 条边的有向图,其中 Morena n处于起点 S , 迷宫的终点设为 T 。 可惜的是 , Morenan 非常的脑小 , 他只会从一个点出发随机沿着一条从该点出发的有向边 , 到达另一个点 。 这样 , Morenan 走的步数可能很长 , 也可能是无限,更可能到不了终点。 若到不了终点,则步数视为无穷大。 但你必须想方设法求出 Morenan 所走步数的期望值。
解题思路
倒着求到终点的期望,按拓扑序求,将所有强连通分量求出来缩点,分量内使用高斯消元求解即可。如果有一条路径不能到达终点即输出inf。
code
using namespace std;
int const mn=1e4+9,mm=1e6+9,mp=100+9,inf=1e9+7;
int n,m,s,t,gra,time,begin[mn],to[mm],next[mm],gr2,begi2[mn],t2[mm],nex2[mm],
dfn[mn],low[mn],inst[mn],st[mn],bel[mn],b[mn],d2[mn],u[mm],v[mm],beg[mn],
end[mn],du[mn],q[mn],tag[mn],re[mn];
LF f[mn],a[mp][mp],a2[mp];
void insert(int u,int v){
to[++gra]=v;
next[gra]=begin[u];
begin[u]=gra;
}
void inser2(int u,int v){
t2[++gr2]=v;
nex2[gr2]=begi2[u];
begi2[u]=gr2;
}
void tarjan(int now){
dfn[now]=low[now]=++time;
inst[st[++st[0]]=now]=1;
fr(i,now)if(!dfn[to[i]]){
tarjan(to[i]);
low[now]=min(low[now],low[to[i]]);
}else if(inst[to[i]])low[now]=min(low[now],dfn[to[i]]);
if(dfn[now]==low[now]){
while(st[st[0]]!=now)bel[st[st[0]]]=now,inst[st[st[0]--]]=0;
bel[st[st[0]]]=now,inst[st[st[0]--]]=0;
}
}
void dfs(int now){
tag[now]=1;
fr(i,now)if(!tag[to[i]])dfs(to[i]);
}
bool cmp(int x,int y){
return bel[x]y];
}
void solve(int l,int r){
int n=r-l+1;
fo(i,1,n)fo(j,1,n+1)a[i][j]=0;
fo(i,l,r){
int now=b[i];
a[i-l+1][i-l+1]=1;a[i-l+1][n+1]=1;
fr(j,now)if(bel[now]==bel[to[j]])
a[i-l+1][re[to[j]]-l+1]+=-1.0/d2[now];
else
a[i-l+1][n+1]+=f[to[j]]/d2[now];
}
fo(i,1,n){
if(!a[i][i]){
fo(j,i+1,n)if(a[j][i])
fo(k,i,n+1)swap(a[i][k],a[j][k]);
}
fo(j,i+1,n){
LF tmp=a[j][i]/a[i][i];
fo(k,i,n+1)a[j][k]-=a[i][k]*tmp;
}
}
fd(i,n,1){
a2[i]=a[i][n+1];
fo(j,i+1,n)a2[i]-=a[i][j]*a2[j];
a2[i]/=a[i][i];
}
fo(i,l,r)f[b[i]]=a2[i-l+1];
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&s,&t);
int tmp=0;
fo(i,1,m){
tmp++;
scanf("%d%d",&u[tmp],&v[tmp]);
if(u[tmp]==t){tmp--;continue;}
insert(u[tmp],v[tmp]);d2[u[tmp]]++;
}
m=tmp;
fo(i,1,n)if(!dfn[i])tarjan(i);
fo(i,1,n)b[i]=i;
sort(b+1,b+n+1,cmp);
fo(i,1,n)re[b[i]]=i;
int i=1;
while(i<=n){
int j=i;
while(bel[b[i]]==bel[b[j]])j++;
beg[bel[b[i]]]=i;
end[bel[b[i]]]=j-1;
i=j;
}
fo(i,1,m)if(bel[u[i]]!=bel[v[i]])inser2(bel[u[i]],bel[v[i]]),du[bel[v[i]]]++;
int he=0,ti=0,ok=1;
fo(i,1,n)if((bel[i]==i)&&(!du[i]))q[++ti]=i;
dfs(s);
while(he!=ti){
int now=q[++he],tmp=ti;
f2(i,now)if((--du[t2[i]])==0)q[++ti]=t2[i];
if((!begi2[now])&&(now!=bel[t]))ok=0;
}
fd(i,ti-1,1)
solve(beg[q[i]],end[q[i]]);
if(tag[t]&&ok)printf("%.3lf\n",f[s]-f[t]);
else printf("INF");
//fo(i,1,n)printf("%.10lf\n",f[i]);
return 0;
}