• bzoj 3143: [Hnoi2013]游走


    题目链接

    bzoj 3143: [Hnoi2013]游走

    题解

    代码

    设经过一个点的期望为p[x],可以得到边的概率为
    (p(e<x,y>)p[x]/d[x] + p[y]/d[y])
    也就是到某条特定的边的期望就是经过这个点的期望值乘上 1/该点的总边数
    那么一条边被经过的期望次数就应该是两端点到这条边的期望值之和
    p[i]表示经过这个点的概率,d[i]表示这个点的度数
    $p[i] = sum_((i,j)∈G)frac{p[i]}{p[j]} $
    发现会产生环,无法递推,因为对与一个点需要旁边点的期望来推,旁边点的期望需要他的期望来推
    我们可以列出方程来高斯消元

    [这个点的概率 imes 1-sum所有相邻的点转移过来的概率=0 ]

    注意,对于节点1我们的相减后上式结果列为1,因为比达,对于节点n,它对其他节点的贡献为0
    这样我们把概率设为未知数,解方程共有n-1个点,列n-1个方程

    /*
    */
    #include<cstdio> 
    #include<algorithm> 
    const int maxn = 1001;
    const int maxm = 1000007; 
    #define eps 1e-8
    inline int read() { 
        int x = 0,f = 1; 
        char c = getchar();
        while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar(); }
        while(c <= '9' && c >= '0')x = x * 10 + c - '0',c = getchar(); 
        return x * f; 
    } 
    int n,m; 
    int head[maxn],d[maxn]; double p[maxm],ans[maxn];int num = 0; 
    
    struct node { 
        int u,v,next; 
    } edge[maxm]; 
    inline void add_edge(int u,int v) {
        edge[++ num].v = v; edge[num].next = head[u];head[u] = num; }  
    double a[maxn][maxn]; 
    int sign(double x) { 
        if(x < eps && x > -eps) return 0; 
        else return x < 0 ? -1 : 1; 
    } 
    void guass() { 
        for(int i = 1;i < n;++ i) { 
            int mx = i; 
            for(int j = i + 1;j < n;++ j) 
                if(sign(a[j][i] - a[mx][i]) > 0)mx = j; 
            if(mx != i) std::swap(a[i],a[mx]); 
            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] -= tmp * a[i][k];
            } 
        } 
        for(int i = n - 1;i >= 1;-- i) {  
            for(int j = i + 1;j < n;++ j) 
                a[i][n] -= ans[j] * a[i][j]; 
            ans[i] = a[i][n] / a[i][i]; 
        } 
    } 
    int S[maxm],T[maxm]; 
    int main() { 
        n = read(), m = read(); 
        for(int u,v,i = 1;i <= m;++ i) { 
            u = read(),v = read();  
            add_edge(u,v);add_edge(v,u);  
            d[u] ++ ,d[v] ++; 
            S[i] = u,T[i] = v;
        } 
        a[1][n] = 1.0; 
        for(int i = 1;i < n;++ i) a[i][i] = 1.0; 
        for(int i = 1;i < n;++ i) 
            for(int j = head[i];j;j = edge[j].next) { 
                if(edge[j].v != n) 
                    a[i][edge[j].v] = (double)-1.0/d[edge[j].v]; 
            } 
        guass(); 
        for(int i = 1;i <= m;++ i) 
            p[i] = ans[S[i]] / (double) d[S[i]] + ans[T[i]] / (double )d[T[i]]; 
        std::sort(p + 1,p + m + 1);
        double Ans = 0;
        for(int i = 1;i <= m;++ i) 
            Ans += p[i] * (m - i + 1); 
        printf("%.3lf
    ",Ans); 
        return 0; 
    } 
    
    
    
  • 相关阅读:
    Ubuntu开源推进全面展开抢占微软市场
    sb600芯片下,操持ubuntu没有声响的要领(ubuntu8.04上乐成)
    centos下设置ssh衔接工夫
    入门linux
    centos下进入单用户情势
    ubuntu hardy下的smtp管事
    MySQL数据库中查找执行从命慢的SQL语句
    mac、xp、linux共存
    Linux和Windows终究哪个更适用
    Debian下的mozilla眷属
  • 原文地址:https://www.cnblogs.com/sssy/p/9162151.html
Copyright © 2020-2023  润新知