• bzoj3143: [Hnoi2013]游走


    http://www.lydsy.com/JudgeOnline/problem.php?id=3143

    计算每条边经过的概率e[]

    然后经过概率多的分配的编号大,经过概率少的分配的编号小

    如何计算边经过的概率?

    假设我们知道点的经过的概率p[]

    若边i连接u和v,那么e[i]=p[u]/d[u]+p[v]/d[v]

    d表示点的度数

    如何计算点的经过概率?

    dp[i]=Σ dp[j]/d[j]

    高斯消元求解

    注意到达终点就不能再走了,所以高斯消元的系数中不涉及和终点有关的信息

    注意起点1的方程是 dp[1]=1+Σ dp[j]/d[j]

    #include<cmath>
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 503
    
    int tot;
    int front[N],to[N*N*2],nxt[N*N*2],from[N*N*2];
    
    double d[N];
    
    double a[N][N];
    
    double e[N*N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void add(int u,int v)
    {
        to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u;
        to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; from[tot]=v;
    }
    
    void gauss(int n)
    {
        int r; double t;
        for(int i=1;i<n;++i)
        {
            r=i;
            for(int j=i+1;j<n;++j)
                if(fabs(a[j][i])>fabs(a[r][i])) r=j;
            if(r!=i) 
                for(int j=1;j<=n;++j) swap(a[i][j],a[r][j]);
            for(int k=i+1;k<n;++k)
            {
                t=a[k][i]/a[i][i];
                for(int j=i;j<=n;++j) a[k][j]-=t*a[i][j];
            }
        }
        for(int i=n-1;i;--i)
        {
            for(int j=i+1;j<n;++j) a[i][n]-=a[i][j]*a[j][n];
            a[i][n]/=a[i][i];
        }
    }
    
    int main()
    {
        int n,m;
        read(n); read(m);
        int u,v;
        for(int i=1;i<=m;++i) 
        {
            read(u); read(v);
            add(u,v);
            d[u]++; d[v]++;
        }
        for(int i=1;i<n;++i)
        {
            a[i][i]=1;
            for(int j=front[i];j;j=nxt[j])
                if(to[j]!=n) a[i][to[j]]-=1/d[to[j]];
        }
        a[1][n]=1;
        gauss(n);
        int cnt=0;
        for(int i=1;i<=tot;i+=2) e[++cnt]=a[from[i]][n]/d[from[i]]+a[to[i]][n]/d[to[i]];
        sort(e+1,e+m+1,greater<double>());
        double ans=0;
        for(int i=1;i<=m;++i) ans+=e[i]*i;
        printf("%.3lf",ans);
    }
  • 相关阅读:
    一二类斯特林数小结
    我的博客搬家了!
    常用编程思想与算法
    【spring专题】spring简介
    九、 Java程序初始化的顺序(二)
    八、 Java程序初始化的顺序(一)
    python的上下文管理
    七、 面向对象(二)
    六、 面向对象基础
    paramiko模块及ssh远程登陆
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8604469.html
Copyright © 2020-2023  润新知