假如我们知道了每条边经过的期望次数,则变成了一个显然的贪心。现在考虑如何求期望次数。
由于走到每个点后各向等概率,很显然一条边的期望次数可以与它的两个端点的期望次数,转化为求点的期望次数
考虑每个点对另个点的贡献,得到方程组,暴力高斯消元
注意走到最后一个点就结束了,所以相当于它不能有出边
#include <bits/stdc++.h> #define eps 1e-6 using namespace std; const int N = 1005; double a[N][N]; int n,m,d[N],g[N][N],t1,t2; bool gauss_jordan() { for(int i=1; i<=n; i++) { int r=i; for(int j=i+1; j<=n; j++) if(fabs(a[j][i])>fabs(a[r][i])) r=j; if(r-i) for(int j=1; j<=n+1; j++) swap(a[i][j],a[r][j]); if(fabs(a[i][i])<eps) return 0; for(int j=1; j<=n; j++) if(j-i) { double tmp=a[j][i]/a[i][i]; for(int k=i+1; k<=n+1; k++) a[j][k]-=a[i][k]*tmp; } } for(int i=1; i<=n; i++) a[i][n+1]/=a[i][i]; return 1; } vector <pair<int,int> > E; double res[N*N]; int main() { ios::sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=m;i++) { cin>>t1>>t2; g[t1][t2]=1; g[t2][t1]=1; d[t1]++; d[t2]++; E.push_back(make_pair(t1,t2)); } a[1][n+1]=1; a[n][n]=1; for(int i=1;i<n;i++) { a[i][i]=1; for(int j=1;j<=n;j++) if(g[j][i]) a[i][j] -= 1.0/d[j]; } gauss_jordan(); double ans = 0; for(int i=0;i<m;i++) res[i]=a[E[i].first][n+1]/d[E[i].first] + a[E[i].second][n+1]/d[E[i].second]; sort(res,res+m); for(int i=0;i<m;i++) ans+=res[i]*(m-i); printf("%.3f\n",ans); }