题目大意
有
n
n
n 个点的有向无环图,求当从
1
1
1 开始等概率选择出边,任何时刻保证存在
1
∼
n
1\sim n
1∼n 的路径,现在你可以阻挡一条边,但要保证依然可以到达
n
n
n 求最小期望步数?
2
≤
N
≤
600
,
N
−
1
≤
M
≤
N
(
N
−
1
)
2
2\le N \le 600,N-1\le M\le \frac{N(N-1)}{2}
2≤N≤600,N−1≤M≤2N(N−1)
思路
你会发现它跟这道题很像:
绿豆蛙的归宿
于是我们倒着算期望
我们记
f
[
i
]
f[i]
f[i] 表示
i
i
i 到
n
n
n 期望步数
我们阻挡对于每个点只会选择
u
u
u 连向的
f
[
v
]
f[v]
f[v] 最大的
因为这样你才会让
1
1
1 到达
n
n
n 的期望步数最小
时间复杂度
O
(
N
(
N
+
M
)
)
O(N(N+M))
O(N(N+M)) 或者
O
(
N
3
)
O(N^3)
O(N3)
#include<set>
#include<map>
#include<cmath>
#include<deque>
#include<stack>
#include<ctime>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<climits>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
int f=1,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=-1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return f*x;
}
#define MAXN 600
queue<int> Q;
int siz[MAXN+5];
int G[MAXN+5][MAXN+5];
double f[MAXN+5],g[MAXN+5];
int main(){
int n=read(),m=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
G[u][v]=1,siz[u]++;
}
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
if(G[i][j])
f[i]+=(f[j]+1)/siz[i];
double ans=f[1];
for(int t=n;t>=1;t--){
if(siz[t]!=1){
int pos=-1;
for(int j=t+1;j<=n;j++)
if(G[t][j]&&(pos==-1||f[j]>f[pos]))
pos=j;
g[t]=0;
for(int j=t+1;j<=n;j++)
if(G[t][j])
if(pos!=j)
g[t]+=(f[j]+1)/(siz[t]-1);
for(int i=t-1;i>=1;i--){
g[i]=0;
for(int j=i+1;j<=n;j++)
if(G[i][j])
g[i]+=(g[j]+1)/siz[i];
}
ans=min(ans,g[1]);
}
g[t]=f[t];
}
printf("%.8lf\n",ans);
return 0;
}