zoukankan      html  css  js  c++  java
  • Bzoj3143: [Hnoi2013]游走

    题面

    Bzoj

    Sol

    (Zsy)又在切大火题了

    考虑暴力,因为它是无穷的,我们可以设(f[i][j])表示走了(i)条边,到达(j)的概率,然后跑(5000)步就有(50)
    那么边经过次数的期望就可以算出来
    对这些边的期望排序,一一编号,注意(n)不要转移

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(505);
    const int __(500005);
    
    IL ll Input(){
        RG char c = getchar(); RG ll x = 0, z = 1;
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int n, m, fst[_], nt[__], cnt, to[__], id[__], dg[_];
    double f[2][_], g[__], ans;
    
    IL void Add(RG int u, RG int v, RG int ID){
        id[cnt] = ID; to[cnt] = v; nt[cnt] = fst[u]; fst[u] = cnt++; ++dg[v];
    }
    
    int main(RG int argc, RG char* argv[]){
        n = Input(); m = Input(); Fill(fst, -1);
        for(RG int i = 1, a, b; i <= m; ++i)
            a = Input(), b = Input(), Add(a, b, i), Add(b, a, i);
        f[0][1] = 1;
        for(RG int d = 1, lst = 0, nxt = 1; d <= 5000; ++d){
            for(RG int u = 1; u < n; ++u){
                if(f[lst][u] == 0) continue;
                for(RG int e = fst[u]; e != -1; e = nt[e]){
                    f[nxt][to[e]] += f[lst][u] / dg[u];
                    g[id[e]] += f[lst][u] / dg[u];
                }
                f[lst][u] = 0;
            }
            swap(lst, nxt);
        }
        sort(g + 1, g + m + 1);
        for(RG int i = 1; i <= m; ++i) ans += g[i] * (m - i + 1);
        printf("%.3lf
    ", ans);
        return 0;
    }
    
    

    考虑优化
    换一种思维,设每条边经过次数的期望为(g[i]),每个点的度数为(dg[i]),到每个点的概率为(f[i])
    设第(i)条边连接(u,v)
    那么(g[i] = frac{f[u]}{dg[u]}+frac{f[v]}{dg[v]})
    (i)连接的点集为(S)
    那么(f[i] = sum_{jin S}frac{f[j]}{dg[j]})
    那么就可以解方程组求出所有的(f[i]),从而(g)也就求出来了
    注意(f[1])最开始为(1),注意(n)不要转移

    # include <bits/stdc++.h>
    # define IL inline
    # define RG register
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(505);
    const int __(500005);
    
    IL ll Input(){
        RG char c = getchar(); RG ll x = 0, z = 1;
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int n, m, fst[_], nxt[__], cnt, to[__], dg[_], ff[__], tt[__];
    double g[__], ans, f[_], a[_][_];
    
    IL void Add(RG int u, RG int v){
    	to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++; ++dg[v];
    }
    
    IL void Gauss(){
    	for(RG int i = 1; i < n; ++i)
    		for(RG int j = i + 1; j <= n; ++j){
    			RG double div = a[j][i] / a[i][i];
    			for(RG int k = 1; k <= n + 1; ++k) a[j][k] -= a[i][k] * div;
    		}
    	for(RG int i = n; i; --i){
    		f[i] = a[i][n + 1] / a[i][i];
    		for(RG int j = i - 1; j; --j) a[j][n + 1] -= f[i] * a[j][i]; 
    	}
    }
    
    int main(RG int argc, RG char* argv[]){
    	n = Input(); m = Input(); Fill(fst, -1);
    	for(RG int i = 1; i <= m; ++i)
    		ff[i] = Input(), tt[i] = Input(), Add(ff[i], tt[i]), Add(tt[i], ff[i]);
    	for(RG int u = 1; u < n; ++u){
    		a[u][u] = -1;
    		for(RG int e = fst[u]; e != -1; e = nxt[e]) a[to[e]][u] = 1.0 / dg[u];
    	}
    	a[n][n] = a[1][n + 1] = -1; Gauss();
    	for(RG int i = 1; i <= m; ++i){
    		if(ff[i] != n) g[i] = f[ff[i]] / dg[ff[i]];
    		if(tt[i] != n) g[i] += f[tt[i]] / dg[tt[i]];
    	}
    	sort(g + 1, g + m + 1);
    	for(RG int i = 1; i <= m; ++i) ans += g[i] * (m - i + 1);
    	printf("%.3lf
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    AtCoder Grand Contest 015 题解
    AtCoder Grand Contest 014 题解
    AtCoder Grand Contest 013 题解
    AtCoder Grand Contest 012 题解
    AtCoder Grand Contest 011 题解
    AtCoder Grand Contest 010 题解
    AtCoder Grand Contest 009 题解
    NOIP2017 Day2 题解
    博客园主题备份
    多项式全家桶
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8405410.html
Copyright © 2011-2022 走看看