题目描述:
无向图,初始1号点,每次随机走,n点结束,问题相当于求每条边的期望经过次数
题目分析:
记
P
k
(
i
)
P_k(i)
Pk(i)为第k步走到i号点的概率(
P
k
P_k
Pk由
P
k
−
1
P_{k-1}
Pk−1转移)
那么边(x,y)在第k步到第k+1步被经过的概率
=
P
k
(
x
)
∗
1
d
[
x
]
+
P
k
(
y
)
∗
1
d
[
y
]
=P_k(x)*\frac 1{d[x]}+P_k(y)*\frac 1{d[y]}
=Pk(x)∗d[x]1+Pk(y)∗d[y]1 (x,y!=n)
记
f
(
i
)
=
∑
k
=
0
∞
P
k
(
i
)
f(i)=\sum_{k=0}^{\infty}P_k(i)
f(i)=∑k=0∞Pk(i)
那么边(x,y)被经过的期望次数
=
f
(
x
)
∗
1
d
[
x
]
+
f
(
y
)
∗
1
d
[
y
]
=f(x)*\frac 1{d[x]}+f(y)*\frac 1{d[y]}
=f(x)∗d[x]1+f(y)∗d[y]1 (x,y!=n)
因为
P
k
P_k
Pk由
P
k
−
1
P_{k-1}
Pk−1转移,所以有如下转移:
f
(
i
)
=
∑
e
[
j
]
[
i
]
,
j
!
=
n
f
(
j
)
∗
1
d
[
j
]
f(i)=\sum_{e[j][i],j!=n}f(j)*\frac 1{d[j]}
f(i)=e[j][i],j!=n∑f(j)∗d[j]1
因为
P
k
(
0
)
=
1
P_k(0)=1
Pk(0)=1,所以
f
(
1
)
f(1)
f(1)要额外+1
至此这题用高斯消元解就可以了。
由于n号点是终点,P(n)不会再继续转移,会发现对于确定的k,
∑
i
P
k
(
i
)
\sum_iP_k(i)
∑iPk(i)在逐渐减小,由最开始等于1,最终收敛于0,所以虽然是无限项,但期望仍然是可求的。
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#define pb(x) push_back(x)
#define maxn 505
using namespace std;
const double eps = 1e-10;
int n,m,x[maxn*maxn],y[maxn*maxn];
vector<int>e[maxn];
double a[maxn][maxn],b[maxn*maxn],ans;
inline bool no(double x){return fabs(x)<eps;}
void Gauss(int N)
{
for(int i=1;i<=N;i++){
if(no(a[i][i])) for(int j=i+1;j<=N;j++) if(!no(a[j][i])) {swap(a[i],a[j]);break;}
if(no(a[i][i])) continue;
for(int j=1;j<=N;j++)
if(i!=j&&!no(a[j][i]))
{
double t=a[j][i]/a[i][i];
for(int k=i;k<=N+1;k++) a[j][k]-=a[i][k]*t;
}
}
for(int i=1;i<=n;i++) a[i][N+1]/=a[i][i];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]),e[x[i]].pb(y[i]),e[y[i]].pb(x[i]);
for(int i=1;i<=n;i++){
a[i][i]=-1;
for(int j=e[i].size()-1;j>=0;j--) if(e[i][j]!=n) a[i][e[i][j]]+=1.0/e[e[i][j]].size();
}
a[1][n+1]=-1;
Gauss(n);
for(int i=1;i<=m;i++){
if(x[i]!=n) b[i]+=a[x[i]][n+1]/e[x[i]].size();
if(y[i]!=n) b[i]+=a[y[i]][n+1]/e[y[i]].size();
}
sort(b+1,b+1+m);
for(int i=1;i<=m;i++) ans+=b[i]*(m-i+1);
printf("%.3f",ans);
}