bzoj 2337: [HNOI2011]XOR和路径
论直接存储无向边会发生什么……
感觉已经不会高斯肖元了呢QAQ
按位考虑,
令\(f_x\)表示\(x\)到\(n\)、xor值为\(1\)的期望
那么对于不是汇点的\(x\)有\(f_x = \frac{\sum f_{in_x} (1 - 2val)+val} {deg_{in_x}}\)
#include <bits/stdc++.h> #define N 110 #define M 20000 #define eps 1e-10 #define LF long double using namespace std; LF ans; int n, m; int ai[M], bi[M], ci[M]; LF mat[N][N]; int s; int out[N]; void put() { for (int i = 1; i <= s; ++ i) { for (int j = 1; j <= s + 1; ++ j) printf("%.3lf ", mat[i][j]); puts(""); } } void G() { //put(); for (int i = 1; i <= s; ++ i) for (int j = i + 1; j <= s; ++ j) if (abs(mat[i][i]) < eps) for (int k = i; k <= s + 1; ++ k) swap(mat[j][k], mat[i][k]); else for (int k = s + 1; k >= i; -- k) mat[j][k] -= mat[j][i] / mat[i][i] * mat[i][k]; for (int i = s; i; -- i) { LF d = mat[i][s + 1]; for (int j = i + 1; j <= s; ++ j) d -= mat[j][s + 1] * mat[i][j]; mat[i][s + 1] = d / mat[i][i]; } //put(); } int main() { scanf("%d%d", &n, &m); s = n; for (int i = 1; i <= m; ++ i) { scanf("%d%d%d", &ai[i], &bi[i], &ci[i]); out[ai[i]] ++; if (bi[i] != ai[i]) out[bi[i]] ++; } for (int p = 0; p <= 30; ++ p) { memset(mat, 0, sizeof mat); for (int i = 1; i <= n; ++ i) mat[i][i] = 1; for (int i = 1; i <= m; ++ i) if (ai[i] != n) if (ci[i] & (1 << p)) mat[ai[i]][bi[i]] += 1.0 / out[ai[i]], mat[ai[i]][n + 1] += 1.0 / out[ai[i]]; else mat[ai[i]][bi[i]] -= 1.0 / out[ai[i]]; for (int i = 1; i <= m; ++ i) if (bi[i] != n && ai[i] != bi[i]) if (ci[i] & (1 << p)) mat[bi[i]][ai[i]] += 1.0 / out[bi[i]], mat[bi[i]][n + 1] += 1.0 / out[bi[i]]; else mat[bi[i]][ai[i]] -= 1.0 / out[bi[i]]; //printf("%d : \n", p); G(); ans += (mat[1][n + 1]) * (1 << p); } printf("%.3lf", (double)ans); }