高斯消元
时间复杂度:(O(n^3))
/*
n行:[0,n)
m列:[0,m)
m=2n时,右侧矩阵是左侧矩阵的逆
m=n+1时,右侧一列是左侧方程组的解
*/
//double
double a[][];
bool gauss(int n,int m){
for(int i=0,r=0;i<n;r=++i){
for(int j=i+1;j<m;++j)if(abs(a[j][i])>abs(a[r][i]))r=j;
if(i^r)for(int j=0;j<m;++j)swap(a[i][j],a[r][j]);
if(abs(a[i][i]-1)<1e-10)return 0;//矩阵非奇异或方程组无解
double b=a[i][i];
for(int j=i;j<m;++j)a[i][j]=a[i][j]/b;
for(int k=0;k<n;++k){
if(k==i)continue;
double p=a[k][i];
for(int j=i;j<m;++j)a[k][j]-=p*a[i][j];
}
}
return 1;
}
//模mod下的解
ll a[][];
bool gauss(int n,int m){
for(int i=0,r=1;i<n;r=++i){
for(int j=i+1;j<n;++j)if(a[j][i]>a[r][i])r=j;
if(i^r)for(int j=0;j<m;++j)swap(a[i][j],a[r][j]);
if(a[i][i]==0)return 0;//矩阵非奇异或方程组无解
ll b=qpow(a[i][i],mod-2);
for(int j=i;j<n;++j)a[i][j]=a[i][j]*b%mod;
for(int k=0;k<n;++k){//第k行
if(k==i)continue;
ll p=a[k][i];
for(int j=i;j<m;++j)a[k][j]=(a[k][j]-p*a[i][j]%mod+mod)%mod;
}
}
return 1;
}
- 随机游走
设(p(k,x))为经过(k(kge 0))步到达x的概率
令:(P(x)=sum_{k=0}^{+infty}p(k,x)\ e(k,x)=kcdot p(k,x)\ E(x)=sum_{k=1}^{+infty}e(k,x)=sum_{k=1}^{+infty}kcdot p(k,x))
到达终点的期望步数(ans= frac{E(x)}{P(x)})
设:
集合(S(x)={y|y通过某条边可以到达x})
out(x)为点x的出度(终点出度为0,即与终点连接的都是单向边)
有下列两个等式:
- (p(k,x)=sum_{yin S(x)}frac{p(k-1,y)}{out(y)},kge 1)且y不能是终点
- (frac{e(k,x)}{k}=sum_{yin S(x)}frac{e(k-1,y)}{(k-1)out(y)},kge 2)且y不能是终点
等式1,k从1累加到(+infty):
(p(k,x)=sum_{yin S(x)}frac{p(k-1,y)}{out(y)})
(Rightarrowsum_{k=1}^{+infty}p(k,x)=sum_{yin S(x)}frac{1}{out(y)}left(sum_{k=1}^{+infty}p(k-1,y) ight))
(Rightarrow P(x)-p(0,x)=sum_{yin S(x)}frac{1}{out(y)}P(y))
(Rightarrow P(x)-sum_{yin S(x)}frac{1}{out(y)}P(y)=p(0,x))
等式2,k从2累加到(+infty):
(frac{e(k,x)}{k}=sum_{yin S(x)}frac{e(k-1,y)}{(k-1)out(y)})
(Rightarrowsum_{k=2}^{+infty}frac{e(k,x)}{k}=sum_{yin S(x)}frac{1}{out(y)}sum_{k=2}^{+infty}frac{e(k-1,y)}{k-1})
(Rightarrowsum_{k=2}^{+infty}e(k,x)=sum_{yin S(x)}frac{1}{out(y)}sum_{k=2}^{+infty}left(1+frac{1}{k-1} ight)cdot e(k-1,y))
(Rightarrow E(x)-e(1,x)=sum_{yin S(x)}frac{1}{out(y)}left(E(y)+sum_{k=2}^{+infty}p(k-1,y) ight))
(Rightarrow E(x)-e(1,x)=sum_{yin S(x)}frac{1}{out(y)}left(E(y)+P(y)-p(0,y) ight))
(Rightarrow E(x)-sum_{yin S(x)}frac{E(y)}{out(y)}=sum_{yin S(x)}frac{P(y)-p(0,y)}{out(y)}+p(1,x))
给定一个没有自环的简单图,从0点出发,求到n-1点的期望步数.
double P[],p0[];
//分别是P(x)和p(0,x)
int main(){
read(n,m);//n个点,m条边
for(int i=0,x,y;i<m;++i){
read(x,y);//xy之间有一条边.
//终点n-1只有入度,没有出度.
if(x!=n-1){
mp[x][y]=1,out[x]++;
}
if(y!=n-1){
mp[y][x]=1,out[y]++;
}
}
p0[0]=1;//只有这一个是1,其余全为零
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
if(mp[j][i]==0)continue;
a[i][j]=-1.0/(double)s[j];
}
a[i][i]=1;
a[i][n]=p0[i];
}
gauss(n,n+1);//求得p(x)
for(int i=0;i<=n;++i)p[i]=a[i][n];
for(int i=0;i<n;++i)for(int j=0;j<=n;++j)a[i][j]=0;
for(int i=0;i<n;++i){
double tot=0;
for(int j=0;j<n;++j){
if(mp[j][i]==0)continue;
a[i][j]=-1.0/(double)s[j];
tot+=(p[j]-p0[j])/(double)s[j];
}
a[i][i]=1;
if(mp[0][i])tot+=1.0/(double)s[0];//与起点相邻的点p(1,x)才不为零
a[i][n]=tot;
}
gauss(n,n+1);
printf("%.5f",a[n-1][n]/p[n-1]);
return 0;
}