这道题说是一道概率题但这种概率实际上就是一道高斯消元。
每个点到的概率等于所以与他相连的点的概率除以相应的边数,构造出来就是个方程组,高斯消元解一波,然后每个点的可能性就是他所连的点的可能性除以边数相加。
最后贪心就好。
代码如下:
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=505;
struct edge
{
int x,y,id;
double sum;
friend bool operator <(edge a,edge b)
{
return a.sum-b.sum>0.000000001;
}
}e[maxn*maxn];
int n,m;
double c[maxn][maxn]={0};
int out[maxn]={0};
bool vis[maxn][maxn]={0};
double d[maxn];
void gauss()
{
int i=1,j=1;
while(i<=n&&j<=n)
{
int t=i;
for(int k=i+1;k<=n;k++) if(fabs(c[k][j])>fabs(c[t][j])) t=k;
if(fabs(c[t][j])>0)
{
if(t!=i)for(int k=j;k<=n+1;k++) swap(c[t][k],c[i][k]);
double tt;
for(int k=i+1;k<=n;k++) if(fabs(c[k][j]))
{
tt=c[k][j]/c[i][j];
for(int x=j;x<=n+1;x++)
c[k][x]-=c[i][x]*tt;
}
i++;
}
j++;
}
for(int i=n;i>=1;i--)
{
for(int j=i+1;j<=n+1;j++)
c[i][n+1]-=c[i][j]*c[j][n+1];
c[i][n+1]/=c[i][i];
}
}
void init()
{
scanf("%d%d",&n,&m);
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&e[i].x,&e[i].y);
vis[e[i].x][e[i].y]=vis[e[i].y][e[i].x]=1;
out[e[i].x]++,out[e[i].y]++;
}
n--;
for(int i=1;i<=n;i++) c[i][i]=-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) if(vis[i][j])
c[i][j]=1.0/(double)out[j];
c[1][n+1]=-1;
gauss();
}
int main()
{
freopen("in.txt","r",stdin);
init();
for(int i=1;i<=m;i++)
e[i].sum=c[e[i].x][n+1]/out[e[i].x]+c[e[i].y][n+1]/out[e[i].y];
sort(e+1,e+1+m);
double ans=0;
for(int i=1;i<=m;i++)
ans+=e[i].sum*i;
printf("%.3lf",ans);
return 0;
}