zoukankan      html  css  js  c++  java
  • 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; 
    } 
    
    
    
  • 相关阅读:
    Windows下如何检测用户修改了系统时间并且把系统时间改回来
    洛谷 1220 关路灯
    洛谷 2279 [HNOI2003]消防局的设立
    洛谷 1498 南蛮图腾
    bzoj 1036 [ZJOI2008]树的统计Count 树链剖分模板
    codevs 1021 玛丽卡 SPFA
    codevs 1077 多源最短路 flyod
    Vijos P1133 装箱问题 01背包
    codevs 1069 关押罪犯 并查集
    codevs 1073 家族 并查集
  • 原文地址:https://www.cnblogs.com/sssy/p/9162151.html
Copyright © 2011-2022 走看看