• [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。

    转载自Navi_Awson巨佬%%%%%oTTTTTTTTTZ

    http://www.cnblogs.com/NaVi-Awson/p/7707368.html

    首先看到路径$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 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 struct Node
     8 {
     9     int next,to;
    10     int dis;
    11 }edge[20005];
    12 double a[105][105],ans;
    13 int n,m,head[105],num,d[105];
    14 int pw[31];
    15 void add(int u,int v,int dis)
    16 {
    17     num++;
    18     edge[num].next=head[u];
    19     head[u]=num;
    20     edge[num].to=v;
    21     edge[num].dis=dis;
    22 }
    23 void gauss()
    24 {int i,j,now,k;
    25   for (i=1;i<=n;i++)
    26     {
    27       now=i;
    28       for (j=i+1;j<=n;j++)
    29         if (fabs(a[now][i])<fabs(a[j][i]))
    30       now=j;
    31       for (j=i;j<=n+1;j++)
    32         swap(a[now][j],a[i][j]);
    33       for (j=i+1;j<=n+1;j++)
    34         a[i][j]/=a[i][i];
    35           a[i][i]=1;
    36       for (j=i+1;j<=n;j++)
    37         {
    38           for (k=i+1;k<=n+1;k++)
    39         a[j][k]-=a[i][k]*a[j][i];
    40           a[j][i]=0;
    41         }
    42     }
    43   for (i=n;i>=1;i--)
    44     {
    45       for (j=i+1;j<=n;j++)
    46         {
    47           a[i][n+1]-=a[i][j]*a[j][n+1];
    48         a[i][j]=0;
    49         }
    50           a[i][n+1]/=a[i][i];
    51           a[i][i]=1;
    52     }
    53 }
    54 int main()
    55 {int i,j,u,v,w;
    56     cin>>n>>m;
    57     pw[0]=1;
    58     for (i=1;i<=30;i++)
    59     pw[i]=pw[i-1]*2;
    60     for (i=1;i<=m;i++)
    61     {
    62         scanf("%d%d%d",&u,&v,&w);
    63         add(u,v,w);
    64         d[v]++;
    65         if (u!=v) add(v,u,w),d[u]++;
    66     }
    67     for (i=0;i<=30;i++)
    68     {
    69         memset(a,0,sizeof(a));
    70         for (u=1;u<n;u++)
    71         {
    72             a[u][u]=d[u];
    73             for (j=head[u];j;j=edge[j].next)
    74             {
    75                 int v=edge[j].to;
    76                 if (edge[j].dis&pw[i]) a[u][v]++,a[u][n+1]++;
    77                 else a[u][v]--;
    78             }
    79         }
    80         a[n][n]=1;
    81         gauss();
    82         ans+=a[1][n+1]*(double)pw[i];
    83     }
    84     printf("%.3lf
    ",ans);
    85 }
  • 相关阅读:
    iOS设计模式-工厂方法
    iOS设计模式-原型模式
    (转)iOS 屏幕适配
    iOS设计模式-MVC
    转 常用第三方库
    学习资料收集
    xcode 插件
    CocoaPods安装和使用
    iOS 友盟统计的bug分析
    HTML——表格
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7709306.html
Copyright © 2020-2023  润新知