• P3211 [HNOI2011]XOR和路径


    https://www.luogu.com.cn/problem/P3211
    用到在 dp 的转移中出现环时,把按顺序转移改为解方程的思路

    整体计算比较困难,考虑把每一位拆开来算
    对于当前位,设 (f_u) 表示从 (u)(n),当前位为 (1) 的概率;设 (deg_u)(u) 的度数,并令 (w(u,v)) 表示边权上当前这一位是 (0/1)
    那么根据异或的性质,就可以得出转移方程:

    [f_u=frac{1}{deg_u}left(sum_{w(u,v)=0}f_v+sum_{w(u,v)=1}(1-f_v) ight) ]

    但发现这是一个一般的图,转移过程中会出现环,那么就可以把他化成方程的形式,用解方程的方法来处理

    [deg_ucdot f_u+sum_{w(u,v)=1}f_v-sum_{w(u,v)=0}f_v=sum_{w(u,v)=1} 1 ]

    这样对于每一个 (1le u le n-1) 都可以写出这样一个方程,对于第 (n) 个方程,由于 (f_n=0),所以直接令 (b_n=0,a_{nn}=1),即可
    最后高斯消元就行了

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #define reg register
    #define LL_INF (long long)(0x3f3f3f3f3f3f3f3f)
    #define INT_INF (int)(0x3f3f3f3f)
    inline int read(){
    	register int x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=getchar();}
    	return y?x:-x;
    }
    #define N 106
    #define M 20006
    struct Graph{
    	int fir[N],nex[M],to[M],w[M],tot;
    	inline void add(reg int u,int v,int z){
    		to[++tot]=v;w[tot]=z;
    		nex[tot]=fir[u];fir[u]=tot;
    	}
    }G;
    int n,m;
    int deg[N],a[N][N];
    double b[N],z[N],f[N];
    double u[N][N],l[N][N];
    inline void lu_div(){
    	for(reg int i=1;i<=n;i++){
    		for(reg int j=i;j<=n;j++){
    			u[i][j]=a[i][j];
    			for(reg int k=1;k<i;k++) u[i][j]-=l[i][k]*u[k][j];
    			l[j][i]=a[j][i];
    			for(reg int k=1;k<i;k++) l[j][i]-=l[j][k]*u[k][i];
    			l[j][i]/=u[i][i];
    		}
    		l[i][i]=1;
    	}
    }
    inline void solve_z(){
    	for(reg int i=1;i<=n;i++){
    		z[i]=b[i];
    		for(reg int j=1;j<i;j++) z[i]-=z[j]*l[i][j];
    	}
    }
    inline void solve_f(){
    	for(reg int i=n;i;i--){
    		f[i]=z[i];
    		for(reg int j=n;j>i;j--) f[i]-=f[j]*u[i][j];
    		f[i]/=u[i][i];
    	}
    }
    inline void solve(){lu_div();solve_z();solve_f();}
    inline void build(int base){
    	for(reg int u=1;u<n;u++){
    		for(reg int j=1;j<=n;j++) a[u][j]=0;
    		b[u]=0;
    		a[u][u]=deg[u];
    		for(reg int v,i=G.fir[u];i;i=G.nex[i]){
    			v=G.to[i];
    			if(G.w[i]&base) a[u][v]++,b[u]++;
    			else a[u][v]--;
    		}
    	}
    	b[n]=0;a[n][n]=1;
    }
    int main(){
    //		std::freopen("out.txt","w",stdout);
    	n=read();m=read();
    	for(reg int u,v,w,i=1;i<=m;i++){
    		u=read();v=read();w=read();
    		G.add(u,v,w);deg[u]++;
    		if(u^v) G.add(v,u,w),deg[v]++;
    	}
    	double ans=0;
    	for(reg int i=0;i<=30;i++){
    		build(1<<i);solve();
    		ans+=f[1]*(1<<i);
    //			for(reg int i=1;i<=n;i++){
    //				for(reg int j=1;j<=n;j++) printf("%d ",a[i][j]);
    //				puts("");
    //			}
    	}
    	printf("%.3lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    JAVA多线程实现的三种方式
    Java String charAt()方法
    三大数据库分页方法
    SSH框架 spring 配置中的: scope="prototype"
    SSH中的Invalid action class configuration that references an unknown class named.......
    String类中toCharArray()方法的用法
    SQL Server中DateTime与DateTime2的区别
    Java 集合系列11之 Hashtable详细介绍(源码解析)和使用示例
    Java 集合系列10之 HashMap详细介绍(源码解析)和使用示例
    哈希表及处理冲突的方法
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/14520667.html
Copyright © 2020-2023  润新知