bzoj2337

高斯消元+概率dp

我好纸张

设dp[i]表示i到n异或和为1的概率,那么暴力高斯消元就行了,注意方程中n那一行要清零

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 105;
struct edge {
    int u, v, w;
} e[N * N];
int n, m;
double ans;
double deg[N], a[N][N];
void gauss_jordan() {
    for(int i = 1; i <= n; ++i) {
        int p = i;
        for(int j = i; j <= n; ++j) {
            if(fabs(a[j][i]) > fabs(a[p][i])) {
                p = j;
            }
        }
        for(int j = 1; j <= n + 1; ++j) {
            swap(a[i][j], a[p][j]);
        }
        double d = a[i][i];
        for(int j = 1; j <= n + 1; ++j) {
            a[i][j] /= d;
        }
        for(int j = 1; j <= n; ++j) {
            if(i != j) {
                double d = a[j][i];
                for(int k = 1; k <= n + 1; ++k) {
                    a[j][k] -= a[i][k] * d;
                }
            }
        }
    }
}
void solve(int bit) {
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= n + 1; ++j) {
            a[i][j] = 0;
        }
    }
    for(int i = 1; i <= n; ++i) {
        a[i][i] = -1;
    }
    for(int i = 1; i <= m; ++i) {
        int t = e[i].w >> bit & 1, u = e[i].u, v = e[i].v;
        if(t) {
            a[u][v] -= 1.0 / deg[u];
            if(u != v) {
                a[v][u] -= 1.0 / deg[v];
            }
            a[u][n + 1] -= 1.0 / deg[u];
            if(u != v) {
                a[v][n + 1] -= 1.0 / deg[v];
            }
        } else {
            a[u][v] += 1.0 / deg[u];
            if(u != v) {
                a[v][u] += 1.0 / deg[v];
            }
        }
    }
    for(int i = 1; i <= n + 1; ++i) {
        a[n][i] = 0;
    }
    a[n][n] = -1;
    gauss_jordan();
    ans += a[1][n + 1] * (1 << bit);
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; ++i) {
        scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
        deg[e[i].u] += 1.0;
        if(e[i].u != e[i].v) {
            deg[e[i].v] += 1.0;
        }
    }
    for(int bit = 0; bit < 30; ++bit) {
        solve(bit);
    }
    printf("%.3f\n", ans);
    return 0;
}
View Code

 

posted @ 2018-03-04 19:00  19992147  阅读(114)  评论(0编辑  收藏  举报