不得不说确实是一道一眼题啊,设
p[i]
表示经过
i
点的期望。
每一条边期望经过的次数为
p[i]/deg[i]+p[j]/deg[j]
,贪心即可。
然而高斯消元有细节要注意,不然会WA。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#define DB double
using namespace std;
const int MAXN=502;
int map[MAXN][MAXN],deg[MAXN],n,m;
DB g[MAXN][MAXN],val[MAXN*MAXN];
void gause()
{
for(int i=1;i<=n-1;i++)
{
int r=i;
for(int j=i+1;j<=n-1;j++)
if(fabs(g[j][i])>fabs(g[r][i]))r=j;
if(r!=i)
for(int j=1;j<=n-1;j++)
swap(g[i][j],g[r][j]);
for(int j=i+1;j<=n-1;j++)
{
{
DB f=g[j][i]/g[i][i];//!!!
for(int k=i;k<=n;k++)
g[j][k]-=f*g[i][k];
}
}
}
for(int i=n-1;i>=1;i--)
{
DB sum=0;
for(int j=i+1;j<=n-1;j++)
sum+=g[i][j]*g[j][n];
g[i][n]-=sum;
g[i][n]/=g[i][i];
g[i][i]=1;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
#endif
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d %d",&x,&y);
map[x][y]=map[y][x]=1;
deg[x]++,deg[y]++;
}
for(int i=1;i<n;i++)
{
if(i==1)g[i][n]=1;
g[i][i]=1;
for(int j=1;j<n;j++)
{
if(j==i)continue;
g[i][j]=-(DB)map[i][j]*1.0/deg[j];
}
}
gause();
int tot=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
if(map[i][j])
val[tot++]=g[i][n]/deg[i]+g[j][n]/deg[j];
}
sort(val,val+tot);
DB ans=0;
int k=tot;
for(int i=0;i<tot;i++)
{
ans+=val[i]*k;
k--;
}
printf("%.3lf\n",ans);
}