一、题目
二、解法
首先判 inf \text{inf} inf 的情况,第一种就是根本到不了终点,第二种就是走到一个岔路口,但是其中一条路到不了终点,那么无论走多少步都没有用,这两个情况还是很好判的。
设
E
(
i
)
E(i)
E(i)为点
i
i
i走到终点的期望步数,转移如下(
i
,
j
i,j
i,j有边相连):
E
(
i
)
=
1
d
e
g
[
i
]
∑
E
(
j
)
+
1
E(i)=\frac{1}{deg[i]}\sum E(j)+1
E(i)=deg[i]1∑E(j)+1这道题的数据直接高斯消元显然不可能,观察数据范围,发现:保证强连通分量的大小不超过 100
,我们可以先缩点,这个图就变成了
d
a
g
dag
dag,每个点内部是需要高斯消元的,但是
d
a
g
dag
dag可以直接转移!我们按拓扑序从大到小处理缩后的点,按上面的转移建立方程组,如果连向自己加入未知元,如果连向外面就可以直接加入常数项了,这么做的时间复杂度是
O
(
1
0
4
n
)
O(10^4n)
O(104n),贴个代码
q
w
q
qwq
qwq
#include <cstdio>
#include <vector>
#include <stack>
using namespace std;
#define eps 1e-8
const int M = 10005;
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,k,s,t,tot,Index,cnt,f[M],deg[M],dfn[M],low[M],in[M];
int bel[M],seq[M],arr[M],pos[M];double a[105][105],E[M];
stack<int> st;vector<int> b[M];
struct edge
{
int v,next;
edge(int V=0,int N=0) : v(V) , next(N) {}
}e[100*M];
void tarjan(int u)
{
dfn[u]=low[u]=++Index;
in[u]=1;st.push(u);
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int v;cnt++;
do
{
v=st.top();st.pop();
b[cnt].push_back(v);
bel[v]=cnt;
in[v]=0;
}while(v^u);
}
}
void Gauss(int n)
{
for(int i=1;i<=n;i++)
{
int r=i;
for(int j=i;j<=n;j++)
if(a[j][i]-a[r][i]>eps)
r=j;
swap(a[i],a[r]);
for(int j=n+1;j>=i;j--)
a[i][j]/=a[i][i];
for(int j=1;j<=n;j++)
{
if(i==j || !a[j][i]) continue;
double tmp=a[j][i]/a[i][i];
for(int k=i+1;k<=n+1;k++)
a[j][k]-=a[i][k]*tmp;
a[j][i]=0;
}
}
}
int main()
{
n=read();m=read();s=read();t=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
e[++tot]=edge(v,f[u]),f[u]=tot;
deg[u]++;
}
tarjan(s);
if(!dfn[t]) {puts("INF");return 0;}
for(int i=1;i<=cnt;i++)
{
k=0;
for(int j=0;j<b[i].size();j++)
arr[i]|=b[i][j]==t,seq[pos[b[i][j]]=++k]=b[i][j];
for(int j=0;j<b[i].size();j++)
for(int l=f[b[i][j]];l;l=e[l].next)
arr[i]|=arr[bel[e[l].v]];
if(!arr[i]) {puts("INF");return 0;}
for(int j=1;j<=k;j++)
for(int l=1;l<=k+1;l++)
a[j][l]=0;
for(int j=0;j<b[i].size();j++)
{
int u=b[i][j],p=pos[u];
a[p][p]=1;
if(u==t) continue;
a[p][k+1]=1;
for(int l=f[u];l;l=e[l].next)
{
int v=e[l].v;
if(bel[v]==i) a[p][pos[v]]-=1.0/deg[u];
else a[p][k+1]+=1.0/deg[u]*E[v];
}
}
Gauss(k);
for(int j=1;j<=k;j++) E[seq[j]]=a[j][k+1];
}
printf("%.3lf\n",E[s]);
}