题目大意:给定一个无向连通图,我们需要给每条边附一个1~m的不重复的权值,使1到n的期望权值和最小
首先贪心思想是求出每条边的期望经过次数 然后对期望值最小的边附加m的权值,第二小的边附加m-1的权值,以此类推。
令f[i]为第i个点的期望经过次数 那么每条边的期望经过次数就是f[x]/d[x]+f[y]/d[y] 其中d[x]表示x的度数
那么显然有:
f[1]=1+Σ[1->j]f[j]/d[j]
f[i]=Σ[i->j]f[j]/d[j] (2<=i<=n-1)
其中f[n]应该等于1,但是由于进入了点n之后就不再出来,因此n点对周围的边和点的贡献都是0,不妨令f[n]=0
那么就有n个未知数n个方程 高斯消元求解即可
然后代入即可出解 注意求的是最小值不是最大值 因此最小的期望值应该乘最大的边权 不要弄反
边集又开小了- - 我是怎么了最近- -
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define M 550
using namespace std;
struct abcd{
int to,next;
}table[M*M<<1];
int head[M],tot;
int n,m,degree[M];
double f[M][M],a[M];
double expectation[M*M],ans;
void Add(int x,int y)
{
degree[x]++;
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
void Gauss_Elimination()
{
int i,j,k;
for(i=1;i<=n;i++)
{
k=i;
for(j=i+1;j<=n;j++)
if( fabs(f[j][i])>fabs(f[k][i]) )
k=j;
for(j=i;j<=n+1;j++)
swap(f[i][j],f[k][j]);
for(k=i+1;k<=n;k++)
{
double temp=-f[k][i]/f[i][i];
for(j=i;j<=n+1;j++)
f[k][j]+=f[i][j]*temp;
}
}
for(i=n;i;i--)
{
for(j=i+1;j<=n;j++)
f[i][n+1]-=f[i][j]*a[j];
a[i]=f[i][n+1]/f[i][i];
}
}
int main()
{
int i,x,y;
cin>>n>>m;
for(i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
Add(x,y),Add(y,x);
}
for(x=1;x<n;x++)
{
f[x][x]-=1;
if(x==1) f[x][n+1]=-1;
for(i=head[x];i;i=table[i].next)
f[x][table[i].to]+=1.0/degree[table[i].to];
}
f[n][n]=1;f[n][n+1]=0;
Gauss_Elimination();
for(i=1;i<=m;i++)
{
x=table[i+i-1].to;
y=table[i<<1].to;
expectation[i]=a[x]/degree[x]+a[y]/degree[y];
}
sort(expectation+1,expectation+m+1);
for(i=1;i<=m;i++)
ans+=(m-i+1)*expectation[i];
cout<<fixed<<setprecision(3)<<ans<<endl;
return 0;
}