题目描述:
有m条边 每条边的代价是经过这条边的次数概率*编号
从1开始到n结束
安排编号,求最小总代价
题目分析:
首先贪心,我们对概率小的边安排大的编号肯定能使的总代价最小…
直接求边的概率不好求,我们从两个点的概率推出这条边的概率
Pe=Pu/du+Pv/dv
P
e
=
P
u
/
d
u
+
P
v
/
d
v
怎么推点的概率啊…
Pi=∑Px/dx
P
i
=
∑
P
x
/
d
x
我们从1出发,那么1的期望本来就有1,而到n结束,那么n对于概率没有贡献,设为0
这样解个n元线性方程组就好了…
别问我为啥n^3可以过500,貌似是高消常数是1/6的关系…
题目链接:
Ac 代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath>
const int maxm=501;
int U[maxm*maxm],V[maxm*maxm];
double a[maxm][maxm],d[maxm],w[maxm*maxm];
int n,m;
inline void Gauss()
{
for(int i=1;i<=n;i++)
{
int r=i;
for(int j=i+1;j<=n;j++) if(std::fabs(a[j][i])>std::fabs(a[r][i])) r=j;
if(r!=i) for(int j=1;j<=n+1;j++) std::swap(a[i][j],a[r][j]);
double t=a[i][i];
for(int j=i+1;j<=n+1;j++) a[i][j]/=t;
for(int j=1;j<=n;j++)
if(i!=j)
{
double t=a[j][i];
for(int k=i+1;k<=n+1;k++) a[j][k]-=a[i][k]*t;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&U[i],&V[i]);
d[U[i]]++,d[V[i]]++;
}
for(int i=1;i<=n;i++) a[i][i]=-1;
a[1][n+1]=-1.0;
for(int i=1;i<=m;i++)
{
a[U[i]][V[i]]+=1/d[V[i]];
a[V[i]][U[i]]+=1/d[U[i]];
}
for(int i=1;i<n;i++) a[n][i]=0;
Gauss();
for(int i=1;i<=m;i++)
w[i]=a[U[i]][n+1]/d[U[i]]+a[V[i]][n+1]/d[V[i]];
std::sort(w+1,w+m+1);
double ans=0;
for(int i=1;i<=m;i++)
{
//printf("%.3lf\n",w[i]);
ans+=w[i]*(m-i+1);
}
printf("%.3lf\n",ans);
return 0;
}