要使得分的期望最小,需要求出每条边的期望经过次数,将这个从小到大排再赋编号m~1就能使得分期望最小
要求出每条边的期望经过次数,我们要先得到每个点的期望经过次数,对于一条边
x−>y
,设
x,y
的度数为
dx,dy
,期望经过次数为
fx,fy
,那么边
x−>y
的期望经过次数为
fxdx+fydy
然后每个点的期望经过次数我们是可以求的,用高斯消元解个方程,注意因为1和n是出发结束点,所以
f[1]
除了相邻点的贡献还要+1,
f[n]
为0
先写炸了精度然后发现高斯消元里面乘爆double了….很不熟练,姿势有问题….
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 505;
const int maxm = 610000;
const long double eps=1e-7;
struct node
{
long double s[maxn],c;
}a[maxn];
long double f[maxn];
int d[maxn];
int e[maxm][2];
int n,m;
long double ef[maxm];
void dfs(int nw)
{
if(nw==n)
{
f[n]=a[n].c/a[n].s[n];
return ;
}
if(abs(a[nw].s[nw])<=eps)
{
for(int i=nw+1;i<=n;i++)
if(abs(a[i].s[nw])>eps)
{
swap(a[nw],a[i]);
break;
}
}
for(int i=nw+1;i<=n;i++)
{
for(int j=nw+1;j<=n;j++)
{
a[i].s[j]=a[i].s[j]-a[nw].s[j]*a[i].s[nw]/a[nw].s[nw];
}
a[i].c=a[i].c-a[nw].c*a[i].s[nw]/a[nw].s[nw];
}
dfs(nw+1);
for(int i=nw+1;i<=n;i++) a[nw].c-=a[nw].s[i]*f[i];
f[nw]=a[nw].c/a[nw].s[nw];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y; scanf("%d%d",&x,&y);
e[i][0]=x; e[i][1]=y;
d[x]++; d[y]++;
}
for(int i=1;i<n;i++) a[i].s[i]=-1;
a[1].c=-1;
for(int i=1;i<=m;i++)
{
int x,y; x=e[i][0],y=e[i][1];
a[x].s[y]=(1.0/(long double)d[y]);
a[y].s[x]=(1.0/(long double)d[x]);
}
for(int i=1;i<=n;i++) a[n].s[i]=0;
a[n].s[n]=1;
dfs(1);
for(int i=1;i<=m;i++)
{
int x=e[i][0],y=e[i][1];
ef[i]=f[x]/(long double)d[x]+f[y]/(long double)d[y];
}
sort(ef+1,ef+m+1);
long double ret=0.0;
for(int i=1;i<=m;i++) ret+=ef[i]*(long double)(m-i+1);
double r=ret;
printf("%.3lf",r);
return 0;
}