zoukankan      html  css  js  c++  java
  • luoguP3232 [HNOI2013]游走 贪心 + 概率期望 + 高斯消元

    首先,题目中的无向简单连通图代表着没有自环,重边...

    总分的期望 = 每条边的期望之和...................每条边的期望又可以拆成$u o v$的期望和$v o u$的期望

    记$f[i]$表示$1 o n$的路径中,$i$的期望经过次数

    而$u o v$的期望只要知道$f[u], f[v]$就可以求出

    注意到,$f[i]$为每个时刻点在$i$的概率之和,即$sumlimits_{t =0}^{infty} p^i_t$

    那么,我们有$f[i] = sumlimits_{t = 0}^{infty} p^i_t = p^i_0 + sumlimits_{(i, v)} frac{1}{du[v]} * sumlimits_{t = 1}^{infty} p^v_t = p^i_0 + sumlimits_{(i, v)} frac{1}{du[v]} * f[v]$

    对于$f[1]$,有$p^1_0 = 1$

    对于其他点,有$p^i_0 = 0$

    列方程即可解决

    注意$n$号节点,一旦到了$n$号节点,游走结束

    因此,尽管$f[n]$在实际中为$1$,但是在方程中为了保证$n$号点不转移,令$f[n] = 0$

    计算边的期望时,$f[n]$同样不参与计算

    最后,求出了每条边的期望经过次数,希望总分期望尽量小

    当然是经过次数多的边给小编号了,贪心即可!

    复杂度$O(n^3)$

    注:$500^2 = 250000$,不知道什么时候才会记住

    注2:少用$luogu;ide$调试,莫名少头文件...

    #include <cmath>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    #define de double
    #define ri register int
    #define sid 505
    #define eid 600005
    
    int n, m, cnp, du[sid];
    de ex[eid], f[sid][sid], g[sid];
    int cap[sid], nxt[eid], node[eid];
    
    inline void adeg(int u, int v) {
        du[u] ++;
        nxt[++ cnp] = cap[u]; cap[u] = cnp; node[cnp] = v;
    }
    
    void Guass() {
        for(ri i = 1; i <= n; i ++) {
            int p = i;
            for(ri j = i; j <= n; j ++) if(fabs(f[j][i]) > fabs(f[p][i])) p = j;
            swap(f[i], f[p]);
            for(ri j = i + 1; j <= n; j ++) {
                de t = f[j][i] / f[i][i];
                for(ri k = i; k <= n + 1; k ++)
                f[j][k] -= t * f[i][k];
            }
        }
        for(ri i = n; i >= 1; i --) {
            f[i][n + 1] = f[i][n + 1] / f[i][i];
            for(ri j = i - 1; j >= 1; j --)
            f[j][n + 1] -= f[i][n + 1] * f[j][i];
        }
        for(ri i = 1; i <= n; i ++) g[i] = f[i][n + 1];
    }
    
    int main() {
        n = read(); m = read();
        for(ri i = 1; i <= m; i ++) {
            int u = read(), v = read();
            adeg(u, v); adeg(v, u);
        }
        #define cur node[j]
        f[1][n + 1] = 1; f[n][n] = 1;
        for(ri i = 1; i < n; i ++) {
            f[i][i] = 1;
            for(ri j = cap[i]; j; j = nxt[j])
            f[i][cur] -= 1.0 / (de)(du[cur]); 
        } 
        Guass();
        int bnp = 0;
        for(ri i = 1; i <= n; i ++)
        for(ri j = cap[i]; j; j = nxt[j])
        ex[++ bnp] = g[i] / (de)du[i] + g[cur] / (de)du[cur];
        sort(ex + 1, ex + bnp + 1);
        de ans = 0;
        for(ri i = 1, j = 1; i <= bnp; i += 2, j ++) 
        ans += ex[i] * (m - j + 1);
        printf("%.3lf
    ", ans); 
        return 0;
    }
  • 相关阅读:
    HOJ 2139 Spiderman's workout(动态规划)
    FZU 2107 Hua Rong Dao(dfs)
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 计算机存储中有多少字节
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 合法括号序列
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
    Java 第十一届 蓝桥杯 省模拟赛 无向连通图最少包含多少条边
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9498038.html
Copyright © 2011-2022 走看看