• BZOJ2337:[HNOI2011]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

    Solution

    Code

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #define N (100+10)
     6 using namespace std;
     7 
     8 struct node{int to,next,len;}edge[N*N*2];
     9 double f[N][N],ans[N],Ans;
    10 int n,m,u,v,l,Ind[N];
    11 int head[N],num_edge;
    12 
    13 void add(int u,int v,int l)
    14 {
    15     edge[++num_edge].to=v;
    16     edge[num_edge].next=head[u];
    17     edge[num_edge].len=l;
    18     head[u]=num_edge;
    19 }
    20 
    21 void Gauss()
    22 {
    23     for (int i=1; i<=n; ++i)
    24     {
    25         int num=i;
    26         for (int j=i+1; j<=n; ++j)
    27             if (fabs(f[j][i])>fabs(f[num][i])) num=j;
    28         if (num!=i) swap(f[i],f[num]);
    29         for (int j=i+1; j<=n; ++j)
    30         {
    31             double t=f[j][i]/f[i][i];
    32             for (int k=i; k<=n+1; ++k)
    33                 f[j][k]-=t*f[i][k];
    34         }
    35     }
    36     for (int i=n; i>=1; --i)
    37     {
    38         for (int j=i+1; j<=n; ++j)
    39             f[i][n+1]-=f[i][j]*ans[j];
    40         ans[i]=f[i][n+1]/f[i][i];
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     scanf("%d%d",&n,&m);
    47     for (int i=1; i<=m; ++i)
    48     {
    49         scanf("%d%d%d",&u,&v,&l);
    50         add(u,v,l);    Ind[u]++;
    51         if (u==v) continue;
    52         add(v,u,l);    Ind[v]++;
    53     }
    54     for (int k=0; k<=30; ++k)
    55     {
    56         memset(ans,0,sizeof(ans));
    57         memset(f,0,sizeof(f));
    58         for (int i=1; i<n; ++i)
    59         {
    60             f[i][i]=1;
    61             for (int j=head[i]; j; j=edge[j].next)
    62                 if ((edge[j].len>>k)&1)
    63                 {
    64                     f[i][edge[j].to]+=(double)1/Ind[i];
    65                     f[i][n+1]+=(double)1/Ind[i];
    66                 }
    67                 else f[i][edge[j].to]-=(double)1/Ind[i];
    68         }
    69         for (int i=1; i<=n-1; ++i) f[n][i]=0;
    70         f[n][n]=1;//钦定结果为0
    71         Gauss();
    72         Ans+=ans[1]*(1<<k);
    73     }
    74     printf("%.3lf
    ",Ans);
    75 }
  • 相关阅读:
    raid阵列算法/数据恢复方法汇总
    EMC Isilon(OneFS)误删文件数据恢复过程<存储数据恢复>
    Raid磁盘阵列更换磁盘时另一块盘离线(v7000存储数据恢复)
    SqlServer数据库无法读取的数据恢复方案实施过程
    ds4800服务器lvm信息丢失数据恢复方案
    Hyper-V数据文件丢失数据恢复过程
    v7000存储数据恢复成功率分析-数据恢复初检报告
    Ext4文件系统fsck后损坏如何恢复?-北亚数据恢复
    服务器raid5两块硬盘离线lvm vxfs文件系统数据恢复过程
    临时表
  • 原文地址:https://www.cnblogs.com/refun/p/8966255.html
Copyright © 2020-2023  润新知