zoukankan      html  css  js  c++  java
  • BZOJ 3143: [Hnoi2013]游走 概率与期望+高斯消元

    Description

    一个无向连通图,顶点从1编号到N,边从1编号到M。
    小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。
    现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

    Input

    第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v≤N),表示顶点u与顶点v之间存在一条边。 输入保证30%的数据满足N≤10,100%的数据满足2≤N≤500且是一个无向简单连通图。

    Output

    仅包含一个实数,表示最小的期望值,保留3位小数。

    给定一个简单无向连通图,求给每个边分配一个边权,使得从 $1$ 号点到 $n$ 号点经过边权和的期望值最小. (分配的边权互不相同,且值域为 $[1,m]$).
    首先有一个结论,$1$ 到 $n$ 号点权和的期望值为 $sum_{i=1}^{m}val[i] imes perc[i],$即每条边的边权乘以走这条边的概率.
    然后,我们发现经过每条边的概率只与这条边两个端点有关,即分别走到两个端点的概率以及两个端点的度数.
    具体地,我们可以列出这样的方程组:($f[i]$ 表示从起点走到 $i$ 的概率)
    $f[i]=sum f[from] imes deg[from].$
    如果这是一个 $DAG,$ 则可以直接来一遍裸的 dp,然而由于有环的存在,只能用高斯消元.
    即将式子变为 $f[i]-sum f[from] imes deg[from]=0.$
    可以将这个看作是关于 $i$ 的一个方程组,列出方程矩阵之后解一下即可.
    特别的,由于肯定会经过 $1$ 号点,所以高斯消元中 $1$ 所对应的那个方程组的常数项为 $1.$

    其实呢,你也可以把这个概率理解为期望经过该点的次数. 

    而你发现在这个情况下这个期望出现的次数和概率是等价的.  

    #include <cmath>         
    #include <cstdio> 
    #include <algorithm>  
    #define N 503 
    #define M 205089
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    double f[N][N],G[M];       
    int edges; 
    int hd[N],to[M<<1],nex[M<<1],deg[N],U[M],V[M];    
    void add(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    }
    void Gauss(int n) 
    { 
        int i,j,k,now; 
        for(i=1;i<=n;++i) 
        {
            now=i;          
            for(j=i;j<=n;++j) 
            {
                if(fabs(f[j][i])>fabs(f[now][i])) now=j;   
            } 
            if(now!=i) 
            {
                for(j=1;j<=n;++j) swap(f[i][j],f[now][j]); 
            } 
            if(f[i][i]) 
            { 
                for(j=i+1;j<=n+1;++j) f[i][j]/=f[i][i]; 
                f[i][i]=1; 
            }
            for(j=i+1;j<=n;++j) 
            {
                double div=f[j][i];    
                for(k=i+1;k<=n+1;++k) f[j][k]-=div*f[i][k];                                          
                f[j][i]=0; 
            }  
        } 
        for(i=n;i>=1;--i) 
        {
            for(j=i+1;j<=n;++j) 
            {
                f[i][n+1]-=f[j][n+1]*f[i][j];    
            }
        }
    }                    
    int main() 
    { 
        int i,j,n,m; 
        // setIO("input");     
        scanf("%d%d",&n,&m);    
        for(i=1;i<=m;++i) 
        {
            int u,v; 
            scanf("%d%d",&u,&v),add(u,v),add(v,u),++deg[u],++deg[v],U[i]=u,V[i]=v;  
        }  
        f[1][n]=1.0; 
        for(i=1;i<n;++i) 
        {
            f[i][i]=1; 
            for(j=hd[i];j;j=nex[j]) 
            {
                int v=to[j]; 
                if(v==n) continue;    
                f[i][v]=-1.0/deg[v];        
            }
        } 
        Gauss(n-1);    
        for(i=1;i<=m;++i) 
        {
            int a=U[i],b=V[i];
            if(a!=n) 
            { 
                G[i]+=f[a][n]*(1.0/deg[a]);    
            } 
            if(b!=n) 
            { 
                G[i]+=f[b][n]*(1.0/deg[b]);  
            }
        } 
        sort(G+1,G+1+m);   
        double ans=0; 
        for(i=1;i<=m;++i) 
        {
            ans+=G[i]*((m-i+1)*1.0); 
        } 
        printf("%.3lf
    ",ans); 
        return 0;    
    }
    

      

  • 相关阅读:
    mono for android学习过程系列教程(6)
    mono for android学习过程系列教程(5)
    mono for android学习过程系列教程(4)
    mono for android学习过程系列教程(3)
    mono for android学习过程系列教程(2)
    mono for android学习过程系列教程(1)
    随笔索引
    中国大学MOOC中的后台文件传输
    知乎控件分享(一)
    知乎UWP 预览
  • 原文地址:https://www.cnblogs.com/guangheli/p/11528077.html
Copyright © 2011-2022 走看看