zoukankan      html  css  js  c++  java
  • 【BZOJ3143】【HNOI2013】游走(期望dp,高斯消元)

    首先想到怎么求出每一条边 i i i 在每次游走中被经过次数的期望 f i f_i fi,那么答案就可以贪心地取。(即让最大的 f i f_i fi 权值设为 1 1 1,次大的设为 2 2 2,……,最小的设为 m m m

    但是发现不好统计,或者时间无法承受。

    发现点数很小( n ≤ 500 nleq 500 n500),于是想到怎么通过点的期望值转移到边上。

    容易得到:如果设每一个点 u u u 在每次游走中被经过次数的期望 g u g_u gu,每个点的度数为 d e g u deg_u degu,然后假设某一条边 i i i ( u , v ) (u,v) (u,v),那么有 f i = g u d e g u + g v d e g v f_i=dfrac{g_u}{deg_u}+dfrac{g_v}{deg_v} fi=degugu+degvgv

    所以我们只需要求出 g g g 就可以得到 f f f 了。

    容易得到状态转移方程:

    g u = { 1 + ∑ ( u , v ) g v d e g v u = 1 ∑ ( u , v ) g v d e g v 1 < u < n g_u= egin{cases} 1+sumlimits_{(u,v)}dfrac{g_v}{deg_v}&u=1\ sumlimits_{(u,v)}dfrac{g_v}{deg_v}&1<u<n\ end{cases} gu=1+(u,v)degvgv(u,v)degvgvu=11<u<n

    解释一下:

    首先为什么 u = 1 u=1 u=1 的时候要比其他时候多加 1 1 1,因为初始化的时候本来就应该是 g 1 = 1 g_1=1 g1=1

    然后为什么 g n g_n gn 不考虑,因为到了 n n n 之后就结束游走了,不可能再走向下一条边。

    然后这个状态转移方程就可以看成是有 n − 1 n-1 n1 个未知数, n − 1 n-1 n1 条式子的方程,用高斯消元做就好了。

    最后代码如下:

    #include<bits/stdc++.h>
    
    #define N 510
    #define M 125010
    
    using namespace std;
    
    int n,m;
    int deg[N],from[M],to[M];
    double a[N][N],x[N],f[M];
    
    vector<int>e[N];
    
    void Gauss()
    {
    	for(int i=1;i<n;i++)
    	{
    		int p=i;
    		for(int j=i+1;j<n;j++)
    			if(fabs(a[j][i])>fabs(a[p][i])) p=j;
    		if(i!=p) swap(a[i],a[p]);
    		for(int j=i+1;j<n;j++)
    		{
    			double tmp=a[j][i]/a[i][i];
    			for(int k=i;k<=n;k++) a[j][k]-=a[i][k]*tmp;
    		}
    	}
    	for(int i=n-1;i>=1;i--)
    	{
    		for(int j=i+1;j<n;j++) a[i][n]-=x[j]*a[i][j];
    		x[i]=a[i][n]/a[i][i];
    	}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&from[i],&to[i]);
    		e[from[i]].push_back(to[i]);
    		e[to[i]].push_back(from[i]);
    		deg[from[i]]++,deg[to[i]]++;
    	}
    	for(int u=1;u<n;u++)
    	{
    		a[u][u]=1;
    		for(int i=0,size=e[u].size();i<size;i++)
    		{
    			int v=e[u][i];
    			if(v!=n) a[u][v]-=1.0/deg[v];
    		}
    	}
    	a[1][n]=1;
    	Gauss();
    	for(int i=1;i<=m;i++)
    	{
    		int u=from[i],v=to[i];
    		if(u!=n) f[i]+=x[u]/deg[u];
    		if(v!=n) f[i]+=x[v]/deg[v];
    	}
    	sort(f+1,f+m+1);
    	double ans=0;
    	for(int i=1;i<=m;i++)
    		ans+=i*f[m-i+1];
    	printf("%.3lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    python,生产环境安装
    neo4j 图数据库
    RNN系列
    机器学习关于AUC的理解整理
    fensorflow 安装报错 DEPENDENCY ERROR
    dubbo Failed to check the status of the service com.user.service.UserService. No provider available for the service
    使用hbase遇到的问题
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk
    gradle 安装
    jenkins 安装遇到的坑
  • 原文地址:https://www.cnblogs.com/ez-lcw/p/14448651.html
Copyright © 2011-2022 走看看