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

    题目描述

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

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

    输入输出格式

    输入格式:

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

    Sol:

    好题……

    我们知道Gauss消元的经典应用就是无向图DP

    数据范围N<=100 ok高斯消元

    然后异或没有办法直接加减之类的就选择按位做

    对于每一位做出期望然后×(1<<k)加起来就行

    于是后面对于每一位做的时侯图就变成只有0/1边

    初始递推式子是f[i]表示i->n的期望值

    所以根据异或的定义 

    (∑u->v∈E) f[v]  = f[u] / du[u] (cst[i] == 0) 

    (∑u->v∈E) f[v] = (1-f[u]) / du[u] (cst[i]==1)

    高斯消元的时候就转化一下 未知数还是老套路dp[i]为第i个未知数就OK

    每次的答案就是a[1][n+1](注意不是ans[1])

    注意无向图自环特判 不然会加两次(样例还是比较良心的)

    Code:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<queue>
     6 #include<vector>
     7 #define ms(a,b) memset(a,b,sizeof a)
     8 #define rep(i,a,n) for(int i = a;i <= n;i++)
     9 #define per(i,n,a) for(int i = n;i >= a;i--)
    10 #define inf 2147483647
    11 using namespace std;
    12 typedef long long ll;
    13 ll read() {
    14     ll as = 0,fu = 1;
    15     char c = getchar();
    16     while(c < '0' || c > '9') {
    17         if(c == '-') fu = -1;
    18         c = getchar();
    19     }
    20     while(c >= '0' && c <= '9') {
    21         as = as * 10 + c - '0';
    22         c = getchar();
    23     }
    24     return as * fu;
    25 }
    26 const int N = 105;
    27 const int M = 20005;
    28 typedef double D;
    29 #define eps 1e-7
    30 //head
    31 int n,m;
    32 int head[N],nxt[M],cst[M],mo[M],cnt;
    33 int du[N];
    34 void _add(int x,int y,int w) {
    35     mo[++cnt] = y;
    36     cst[cnt] = w;
    37     nxt[cnt] = head[x];
    38     head[x] = cnt;
    39 }
    40 void add(int x,int y,int w) {
    41     if(x^y) _add(x,y,w), _add(y,x,w),du[x]++,du[y]++;
    42     else _add(x,x,w),du[x]++;
    43 }
    44 
    45 D a[N][N],ans[N];
    46 D Ans;
    47 void Gauss() {
    48     rep(i,1,n) {
    49         int maxx = i;
    50         rep(j,i+1,n) if(fabs(a[j][i]) > fabs(a[maxx][i])) maxx = j;
    51         if(maxx ^ i) swap(a[maxx],a[i]);
    52         D div = a[i][i];
    53         rep(j,i,n+1) a[i][j] /= div;
    54         rep(j,1,n) {
    55             if(j == i || !a[j][i]) continue;
    56             div = a[j][i];
    57             rep(k,i,n+1) a[j][k] -= div * a[i][k];
    58         }
    59     }
    60 }
    61 //这里就是上面求f[]的式子移项一下
    62 void init(int k) {
    63     ms(a,0);
    64     rep(x,1,n-1) {
    65         a[x][x] = 1.0;
    66         for(int i = head[x]; i; i = nxt[i]) {
    67             int sn = mo[i];
    68             if(cst[i] & (1<<k)) {
    69                 a[x][sn] += 1.0/du[x];
    70                 a[x][n+1] += 1.0/du[x];
    71             } else a[x][sn] -= 1.0/du[x];
    72         }
    73     }
    74     a[n][n] = 1.0;
    75     return;
    76 }
    77 
    78 int main() {
    79     n = read();
    80     m = read();
    81     rep(i,1,m) {
    82         int x = read(),y = read(),w = read();
    83         add(x,y,w);
    84     }
    85     rep(i,0,30) {
    86         init(i);
    87         Gauss();
    88         Ans += a[1][n+1] * D(1<<i);//所有点到n的期望和
    89     }
    90     printf("%.3lf
    ",Ans);
    91     return 0;
    92 }

    稳妥

    > 别忘了 总有人在等着你
  • 相关阅读:
    java扫描文件夹下面的所有文件(递归与非递归实现)
    JAVA8 十大新特性详解
    Intellij IDEA创建的Web项目配置Tomcat并启动Maven项目
    Spring官网下载各版本jar包
    史上最全Java面试题(带全部答案)
    深入JVM对象引用
    23种设计模式全解析
    git difftool和mergetool图形化
    Java技术——你真的了解String类的intern()方法吗
    动手实现一个vue中的模态对话框组件
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/9736736.html
Copyright © 2011-2022 走看看