zoukankan      html  css  js  c++  java
  • BZOJ2337 [HNOI2011]XOR和路径

    题意:有一个无向图。边带权,从点1開始,每次随机选择与这个点相邻的一条边走到还有一个点,直到走到点n.权值为全部走过的边的异或和(若一条边经过多次则被异或多次),求权值的期望值。


    思路:将每一位拆开。那么相当于边上的权值仅仅有0,1.

    因为到达n就马上停止,我们定义f[i]表示从i到达n的期望值。

    那么显然f[n]=0,对于i!=n,我们列出其转移方程:

    for all x near i if (Edge(x,i)==0) f[i]+=f[x]/du[i] else f[i]+=(1-f[x])/du[i].(大概是这个意思)

    然后就有n-1个方程,有高斯消元求解就可以。

    终于的答案就是f[1]*2^i(如果当前是第i位)

    将全部位的答案累加就可以。


    Code:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    typedef double f2;
     
    #define N 110
    #define M 10010
     
    int head[N], next[M << 1], end[M << 1], len[M << 1], du[N];
    void addedge(int a, int b, int _len) {
        static int q = 1;
        len[q] = _len;
        end[q] = b;
        next[q] = head[a];
        head[a] = q++;
    }
     
    f2 A[N][N];
     
    #define _abs(x) ((x)>0?

    (x):-(x)) void Gauss(int n) { register int i, j, k; f2 tmp; for(i = 1; i <= n; ++i) { k = i; for(j = i + 1; j <= n; ++j) if (_abs(A[j][i]) > _abs(A[k][i])) k = j; if (k != i) for(j = i; j <= n + 1; ++j) swap(A[i][j], A[k][j]); for(j = i + 1; j <= n; ++j) { tmp = -A[j][i] / A[i][i]; A[j][i] = 0; for(k = i + 1; k <= n + 1; ++k) A[j][k] += tmp * A[i][k]; } } for(i = n; i >= 1; --i) { for(j = i + 1; j <= n; ++j) A[i][n + 1] -= A[j][n + 1] * A[i][j]; A[i][n + 1] /= A[i][i]; } } int main() { #ifndef ONLINE_JUDGE freopen("tt.in", "r", stdin); #endif int n, m; scanf("%d%d", &n, &m); register int i, j; int a, b, x; for(i = 1; i <= m; ++i) { scanf("%d%d%d", &a, &b, &x); if (a != b) { ++du[a], ++du[b]; addedge(a, b, x); addedge(b, a, x); } else { ++du[a]; addedge(a, a, x); } } f2 res = 0; for(int bit = 0; bit < 30; ++bit) { memset(A, 0, sizeof(A)); for(i = 1; i < n; ++i) { A[i][i] = 1; for(j = head[i]; j; j = next[j]) { if ((len[j] >> bit) & 1) A[i][n + 1] += 1 / (f2)du[i], A[i][end[j]] += 1 / (f2)du[i]; else A[i][end[j]] -= 1 / (f2)du[i]; } } A[n][n] = 1; Gauss(n); res += A[1][n + 1] * (1 << bit); } printf("%.3lf", res); return 0; }



  • 相关阅读:
    luarocks argparse
    Shell中for循环的几个常用写法
    linux
    Docker修改镜像源为阿里云
    ntpdate更新服务器时间失败
    linux文本三剑客之 sed
    [Union]C++中Union学习笔记
    [sublime] 利用sublime搭建C/C++编译器
    [wordpress]WordPress地址(URL)错误,修改解决方案
    [wordpress]更新插件时,免去FTP操作
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7205868.html
Copyright © 2011-2022 走看看