您的位置:首页 > 其它

[BZOJ3143][HNOI2013]游走

2016-03-24 20:08 309 查看
不得不说确实是一道一眼题啊,设p[i]p[i]表示经过ii点的期望。

p[i]=p[j]/deg[j]+[i==1],i→jp[i]=p[j]/deg[j]+[i==1],i\rightarrow j,高斯消元即可。

每一条边期望经过的次数为p[i]/deg[i]+p[j]/deg[j]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]
;
g[i]
-=sum;
g[i]
/=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]
=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]
/deg[i]+g[j]
/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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: