zoukankan      html  css  js  c++  java
  • BZOJ2337 [HNOI2011]XOR和路径 【概率dp + 高斯消元】

    题目

    题解

    突然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
    ",ans);
    	return 0;
    }
    
    
    
  • 相关阅读:
    实现主从关系Form中汇总行金额/数量
    Custom.pll : 客制化菜单
    XML publisher 填充空白行数
    PLSQL提交带有模板的报表的方法
    使用Form个性化修改标准Form的LOV2
    在开发Form表单中的三种查询方法
    S3C2440 I2C实现
    NBOOT 基于VS2005的编程与编译(一)
    WINCE 6.0 调大image config.bib
    少用的defined,注意不是define
  • 原文地址:https://www.cnblogs.com/Mychael/p/8640627.html
Copyright © 2011-2022 走看看