给你一个有向图 , , 问从 S S 走到 T T 的期望步数
如果存在一条路径从 S S 出发走不到 T, T , 那么期望就是 inf inf
保证每个强连通分量大小 ≤100 ≤ 100
先考虑怎么判无解
如果一个点满足 S S 能到 , , 且他没有出度 , , 那么就一定无解
如果 S S 不能到 T T 一样无解
无向图很好做直接列 n n 个方程然后高消即可
考虑有向图怎么做 , , 首先先 tarjan t a r j a n 缩环
还是考虑经典的 dp,f[u] d p , f [ u ] 表示 u u 走到 T T 的期望步数 ,dg[u] , d g [ u ] 表示 u u 的出度
所以考虑对于同一个强联通分量里的点高斯消元
考虑到 f[u] f [ u ] 可能已经有值 , , 并且不是所有的 u→v∈E u → v ∈ E 都满足 belongu=belongv b e l o n g u = b e l o n g v
所以每个方程的第 n+1 n + 1 项应该是 f[u]+1dg[u]∑u→v∈E[belongu=belongv] f [ u ] + 1 d g [ u ] ∑ u → v ∈ E [ b e l o n g u = b e l o n g v ]
#include
#define fp(i,a,b) for(register int i=a,I=b+1;i
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define Go(u) for(register int i=Fi[u],v=E[i].to;i;v=E[i=E[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
char ss[1<<17],*A=ss,*B=ss;
inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
template<class T>inline void sd(T&x){
char c;T y=1;while(c=gc(),(c<48||571)if(c==45)y=-1;x=c-48;
while(c=gc(),4758)x=x*10+c-48;x*=y;
}
const int N=1e4+5,Eg=1e6+5,M=105;
const double eps=1e-13;
typedef int arr[N];
typedef double db;
struct eg{int nx,to;}e[Eg],E[Eg];
int n,m,dft,Cnt,Top,p[N][M];
arr fi,Fi,bl,in,id,dfn,low,vis,S,Sum;db f[N],dg[N],ans[M],G[M][M];
void tarjan(int u){
dfn[u]=low[u]=++dft;S[++Top]=u;vis[u]=1;
go(u)
if(!dfn[v])tarjan(v),cmin(low[u],low[v]);
else if(vis[v])cmin(low[u],dfn[v]);
if(dfn[u]==low[u]){
int v;++Cnt;
do{
bl[v=S[Top--]]=Cnt;vis[v]=0;
p[Cnt][id[v]=++Sum[Cnt]]=v;
}while(v^u);
}
}
inline void add(int u,int v){static int ce=0;e[++ce]={fi[u],v},fi[u]=ce;}
inline void ADD(int u,int v){static int ce=0;E[++ce]={Fi[u],v},Fi[u]=ce;}
inline int cmp(db x){return fabs(x)0:x<0?-1:1;}
inline void Gauss(int n){
db t;int mx;
fp(i,1,n){mx=i;
fp(j,i,n)if(cmp(G[mx][i]-G[j][i])<0)mx=j;
if(mx^i)fp(j,i,n+1)swap(G[mx][j],G[i][j]);
fp(j,i+1,n){
t=G[j][i]/G[i][i];
fp(k,i,n+1)G[j][k]-=G[i][k]*t;
}
}
fd(i,n,1){
fp(j,i+1,n)G[i][n+1]-=G[i][j]*ans[j];
ans[i]=G[i][n+1]/G[i][i];
}
fp(i,1,n)fp(j,1,n+1)G[i][j]=0;
}
inline void Topsort(int Pos){
register int h=1,t=1,nw,u,s;
static int q[N];q[1]=bl[Pos];
fp(u,1,n)Go(u)if(bl[u]^bl[v])++in[bl[v]];
while(h<=t){
nw=q[h++];s=Sum[nw];
fp(x,1,s){
u=p[nw][x];G[x][x]=1,G[x][s+1]=f[u];
if(u==Pos)continue;
go(u)if(bl[u]==bl[v])
G[x][s+1]+=dg[u],
G[x][id[v]]-=dg[u];
}
Gauss(s);
fp(x,1,s){
u=p[nw][x],f[u]=ans[x];
Go(u)if(bl[u]^bl[v]){
if(!(--in[bl[v]]))q[++t]=bl[v];
f[v]+=(f[u]+1)*dg[v];
}
}
}
}
int main(){
#ifndef ONLINE_JUDGE
file("s");
#endif
int u,v,S,T;
sd(n),sd(m),sd(S),sd(T);
while(m--)sd(u),sd(v),add(u,v),ADD(v,u),++dg[u];
tarjan(S);
fp(i,1,n)
if(i^T){if(dfn[i]&&!dg[i])return puts("INF"),0;if(dg[i])dg[i]=1/dg[i];}
else if(!dfn[i])return puts("INF"),0;
Topsort(T);
printf("%.3lf\n",f[S]);
return 0;
}