码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ2337 [HNOI2011]XOR和路径 【概率dp + 高斯消元】

时间:2018-03-24 18:32:07      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:ios   mat   get   exit   out   log   amp   分享   clu   

题目

技术分享图片

题解

突然get到这样路径期望的题目八成是高斯消元
因为路径上的dp往往具有后效性,这就形成了一个方程组

对于本题来说,直接对权值dp很难找到突破口
但是由于异或是位独立的,我们考虑求出每一位的期望

\(f[i]\)为从节点\(i\)出发到达N的期望值
\(f[i] = \frac{f[j]}{degree[i]} + \frac{1 - f[k]}{degree[i]} [edge(i,j) = 0,edge(i,k) = 1]\)
因为如果出边权值为0,异或之后值不变,等于\(f[j]\)的值,
如果权值为1,异或后取反,等于\(1-f[k]\)
同时\(f[n] = 0\)
列出式子后就是一个n元方程组

最后要注意自环只算该点的一条边

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define eps 1e-9
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
using namespace std;
const int maxn = 105,maxm = 100005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57) {if (c == ‘-‘) flag = -1; c = getchar();}
    while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - 48; c = getchar();}
    return out * flag;
}
int h[maxn],ne = 2;
double de[maxn];
struct EDGE{int to,nxt,w;}ed[maxm];
inline void build(int u,int v,int w){
    ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;
    if (u != v){
        ed[ne] = (EDGE){u,h[v],w}; h[v] = ne++;
        de[u] += 1,de[v] += 1;
    }
    else de[u] += 1;
}
int n,m,p;
double A[maxn][maxn],ans;
void gause(){
    for (int i = 1; i <= n; i++){
        int j = i;
        for (int k = i + 1; k <= n; k++)
            if (fabs(A[k][i]) > fabs(A[j][i])) j = k;
        if (fabs(A[j][i]) < eps) exit(0);
        double t = A[j][i];
        for (int k = i; k <= n + 1; k++) swap(A[i][k],A[j][k]),A[i][k] /= t;
        for (j = i + 1; j <= n; j++){
            if (fabs(A[j][i]) > eps){
                t = A[j][i];
                for (int k = i; k <= n + 1; k++)
                    A[j][k] -= A[i][k] * t;
            }
        }
    }
    for (int i = n; i; i--){
        for (int j = n; j > i; j--)
            A[i][n + 1] -= A[i][j] * A[j][n + 1];
        A[i][n + 1] /= A[i][i];
    }
}
void solve(){
    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] = de[i];
        Redge(i){
            if ((ed[k].w >> p) & 1){
                A[i][n + 1] += 1.0;
                A[i][ed[k].to] += 1.0;
            }else A[i][ed[k].to] -= 1.0;
        }
    }
    A[n][n] = 1;
    gause();
    ans += (1 << p) * A[1][n + 1];
}
int main(){
    n = read(); m = read();
    int a,b,w;
    for (int i = 1; i <= m; i++){
        a = read(); b = read(); w = read();
        build(a,b,w);
    }
    for (p = 0; (1 << p) <= INF; p++) solve();
    printf("%.3lf\n",ans);
    return 0;
}

BZOJ2337 [HNOI2011]XOR和路径 【概率dp + 高斯消元】

标签:ios   mat   get   exit   out   log   amp   分享   clu   

原文地址:https://www.cnblogs.com/Mychael/p/8640627.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!