zoukankan      html  css  js  c++  java
  • [HNOI 2011]XOR和路径

    Description

    给定一个无向连通图,其节点编号为 1 到 N,其边的权值为非负整数。试求出一条从 1 号节点到 N 号节点的路径,使得该路径上经过的边的权值的“XOR 和”最大。该路径可以重复经过某些节点或边,当一条边在路径中出现多次时,其权值在计算“XOR 和”时也要被重复计算相应多的次数。

    直接求解上述问题比较困难,于是你决定使用非完美算法。具体来说,从 1 号节点开始,以相等的概率,随机选择与当前节点相关联的某条边,并沿这条边走到下一个节点,重复这个过程,直到走到 N 号节点为止,便得到一条从 1 号节点到 N 号节点的路径。显然得到每条这样的路径的概率是不同的并且每条这样的路径的“XOR 和”也不一样。现在请你求出该算法得到的路径的“XOR 和”的期望值。

    Input

    从文件input.txt中读入数据,输入文件的第一行是用空格隔开的两个正整数N和M,分别表示该图的节点数和边数。紧接着的M行,每行是用空格隔开的三个非负整数u,v和w(1≤u,v≤N,0≤w≤109),表示该图的一条边(u,v),其权值为w。输入的数据保证图连通,30%的数据满足N≤30,100%的数据满足2≤N≤100,M≤10000,但是图中可能有重边或自环。

    Output

    输出文件 output.txt 仅包含一个实数,表示上述算法得到的路径的“XOR 和”的期望值,要求保留三位小数。(建议使用精度较高的数据类型进行计算)

    Sample Input

    2 2
    1 1 2
    1 2 3

    Sample Output

    2.333

    HINT

    样例解释:有1/2的概率直接从1号节点走到2号节点,该路径的“XOR和”为3;有1/4的概率从1号节点走一次1号节点的自环后走到2号节点,该路径的“XOR和”为1;有1/8的概率从1号节点走两次1号节点的自环后走到2号节点,该路径的“XOR和”为3;„„;依此类推,可知“XOR和”的期望值为:3/2+1/4+3/8+1/16+3/32+„„=7/3,约等于2.333。

    题解

    首先看到路径$xor$值,还是选择按位做。

    我们设$f_u$表示从$u$到$n$的路径异或值为$1$的概率。显然$f_n == 0$。

    此外,设$w(u, v)$为$u->v$的边权($1/0$),那么有:

    $$f_u = sum_{(u,v) in E, w(u,v) = 0} frac{f_v}{degree_u} + sum_{(u,v) in E, w(u,v) = 1} frac{1-f_v}{degree_u}$$

    那么我们可以得到$n$个方程,用高斯消元求解。

    可以乘上$degree_u$减小误差。

    这题特殊说明一下为什么不能顺推而要逆推:

    很多题解的说法是因为“如果正推的话,$1−f_i$代表的不仅从$1$到$i$异或和不为$1$的概率,还包含了从$1$不走到$i$的概率,无法转移”。

    如果这样解释,那就解释不了$i$走不到$n$的情况。

    我认为合理的解答是:因为$1$可以重复走多次,而$n$只能走$1$次。

     1 //It is made by Awson on 2017.10.21
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <stack>
     7 #include <queue>
     8 #include <vector>
     9 #include <string>
    10 #include <cstdio>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Min(a, b) ((a) < (b) ? (a) : (b))
    17 #define Max(a, b) ((a) > (b) ? (a) : (b))
    18 #define Abs(x) ((x) < 0 ? (-(x)) : (x))
    19 using namespace std;
    20 const int N = 100;
    21 const int M = 10000;
    22 int st[32];
    23 
    24 int n, m, u, v, w;
    25 struct tt {
    26     int to, cost, next;
    27 }edge[(M<<1)+5];
    28 int path[N+5], top, degree[N+5];
    29 double A[N+5][N+5], ans;
    30 
    31 double Gauss() {
    32     for (int line = 1; line <= n; line++) {
    33         int max_line = line;
    34         for (int i = line+1; i <= n; i++) if (fabs(A[i][line]) > fabs(A[max_line][line])) max_line = i;
    35         if (max_line != line) swap(A[line], A[max_line]);
    36         for (int i = line+1; i <= n; i++) {
    37             double div = A[i][line]/A[line][line];
    38             for (int j = line; j <= n+1; j++) A[i][j] -= A[line][j]*div;
    39         }
    40     }
    41     for (int i = n; i >= 1; i--) {
    42         for (int j = i+1; j <= n; j++)
    43             A[i][n+1] -= A[i][j]*A[j][n+1];
    44         A[i][n+1] /= A[i][i];
    45     }
    46     return A[1][n+1];
    47 }
    48 void add(int u, int v, int w) {
    49     edge[++top].to = v;
    50     edge[top].cost = w;
    51     edge[top].next = path[u];
    52     path[u] = top; degree[v]++;
    53 }
    54 void work() {
    55     st[0] = 1; for (int i = 1; i <= 30; i++) st[i] = st[i-1]<<1;
    56     scanf("%d%d", &n, &m);
    57     for (int i = 1; i <= m; i++) {
    58         scanf("%d%d%d", &u, &v, &w);
    59         add(u, v, w); if (u != v) add(v, u, w);
    60     }
    61     for (int i = 0; i <= 30; i++) {
    62         memset(A, 0, sizeof(A));
    63         for (int u = 1; u < n; u++) {
    64             A[u][u] = degree[u];
    65             for (int j = path[u]; j; j = edge[j].next) {
    66                 if (st[i]&edge[j].cost) A[u][edge[j].to] += 1., A[u][n+1] += 1.;
    67                 else A[u][edge[j].to] -= 1.;
    68             }
    69         }
    70         A[n][n] = 1;
    71         ans += Gauss()*(double)st[i];
    72     }
    73     printf("%.3lf
    ", ans);
    74 }
    75 int main() {
    76     work();
    77     return 0;
    78 }
  • 相关阅读:
    js练习题2
    js样式
    js小练习
    css动画样式
    css盒子、布局样式
    css一般样式
    css样式、选择器
    html表格、表单
    html 标签
    mysql连接查询,子查询,联合查询
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7707368.html
Copyright © 2011-2022 走看看