luogu P3232 [HNOI2013]游走

Posted 275307894a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P3232 [HNOI2013]游走相关的知识,希望对你有一定的参考价值。

题面传送门
真是我学习高斯消元以来的做过最正经的一道题目。
编号这个东西不太好做,但是我们如果把每条边经过的次数算出来然后排序后赋权就可以达到最小。
所以是算每条边出现的期望次数。
然后因为\\(m\\)太大实在不好弄,但是因为是随机跑的所以只要找到两端点出现次数然后除以度数加起来即可。
显然可以建立方程,然后高斯消元解出来即可。
时间复杂度\\(O(n^3)\\)
code:

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<algorithm>
#include<bitset>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define l(x) x<<1
#define r(x) x<<1|1
#define re register
#define ll long long
#define db double
#define S 10000000
#define N 500
#define eps (1e-6)
#define mod 1000000007
using namespace std;
int n,m,in[N+5],x[N*N+5],y[N*N+5],now;double p[N+5][N+5],ans[N+5],pus,z[N*N+5];
struct yyy{int to,z;}tmp;
struct ljb{
	int head,h[N+5];yyy f[N*N+5<<1];
	I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}
}s;
I void swap(db &x,db &y){db z=x;x=y;y=z;}
int main(){
	freopen("1.in","r",stdin);
	re int i,j,k;scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]),in[x[i]]++,in[y[i]]++,s.add(x[i],y[i]),s.add(y[i],x[i]);
	for(i=1;i<n;i++) {
		for(int j=s.h[i];j;j=tmp.z) tmp=s.f[j],p[i][tmp.to]=1.0/in[tmp.to];i==1&&(p[1][n+1]=-1);p[i][i]=-1;
	}
	for(i=1;i<n;i++){
		for(now=i,j=i+1;j<=n+1;j++)p[j][i]>p[now][i]&&p[j][i]&&(now=j);
		for(j=1;j<=n+1;j++) swap(p[i][j],p[now][j]); 
		for(pus=p[i][i],j=i;j<=n+1;j++) p[i][j]/=pus;
		for(j=i+1;j<=n;j++){
			for(pus=p[j][i],k=i;k<=n+1;k++) p[j][k]-=pus*p[i][k];
		}
	}
	for(ans[n]=p[n][n+1],i=n-1;i;i--){
		ans[i]=p[i][n+1];for(j=i+1;j<=n;j++) ans[i]-=ans[j]*p[i][j];
	}
	for(i=1;i<=m;i++) z[i]=ans[x[i]]/in[x[i]]+ans[y[i]]/in[y[i]];sort(z+1,z+m+1);
	for(pus=0,i=1;i<=m;i++) pus+=z[i]*(m-i+1);printf("%.3lf\\n",pus);
} 

以上是关于luogu P3232 [HNOI2013]游走的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3143HNOI2013游走

BZOJ 3143: [Hnoi2013]游走

HNOI2013游走

bzoj 3143 [Hnoi2013]游走 期望dp+高斯消元

游走[HNOI2013]

[HNOI2013]游走