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);
}

 

posted @ 2017-01-25 20:37  AwD!  阅读(439)  评论(1编辑  收藏  举报