考虑计算每条边被经过的期望,然后贪心给编号
但是因为是无向边,所以不好计算
那就计算点的期望,边的期望就是两个端点的期望来除以度数再加起来
点的期望可以直接高斯消元算
Code:
#include<bits/stdc++.h>
#define db double
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=605,M=360000;
int vis[M<<1],head[M<<1],nxt[M<<1],tot=0;
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
int x[M<<1],y[M<<1],in[N];
int n,m;
db ans,f[N][N],xx[N],g[M<<1];
inline void gauss(){
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=n+1;k>=i;k--) f[j][k]-=f[i][k]*f[j][i]/f[i][i];
for(int i=n;i;i--){
xx[i]=f[i][n+1];
for(int j=n;j>=i+1;j--) xx[i]-=f[i][j]*xx[j];
xx[i]/=f[i][i];
}
}
int main(){
n=read();m=read();
for(int u,v,i=1;i<=m;i++){
u=read(),v=read();
add(u,v);add(v,u);
++in[u],++in[v];
x[i]=u,y[i]=v;
}
for(int i=1;i<n;i++){
f[i][i]=1;
for(int j=head[i];j;j=nxt[j]) if(vis[j]!=n) f[i][vis[j]]-=1.0/in[vis[j]];
}
f[1][n+1]=1;f[n][n]=1;
gauss();
for(int i=1;i<=m;i++) g[i]=xx[x[i]]/in[x[i]]+xx[y[i]]/in[y[i]];
sort(g+1,g+m+1);
for(int i=1;i<=m;i++) ans+=g[i]*(m-i+1);
printf("%.3lf",ans);
return 0;
}