BZOJ2337:[HNOI2011]XOR和路径——题解

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

——————————————————————————————————————————

http://www.lydsy.com/JudgeOnline/problem.php?id=2337

            2  3  6

 不会期望怎么办?看题解……

参考:http://blog.csdn.net/PoPoQQQ/article/details/42223843

我们考虑将xor的操作分解成对每一位的操作,然后将边权拆成当前位,模拟xor操作即可。

剩下来的操作就和我的上一篇博客(BZOJ3143)基本上相同了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef double dl;
const int N=105;
const int M=10005;
struct node{
    int to,nxt,w;
}e[M*2];
int head[N],cnt,d[N];
inline void add(int u,int v,int w){
    cnt++;
    e[cnt].to=v;
    e[cnt].w=w;
    e[cnt].nxt=head[u];
    head[u]=cnt;
    d[u]++;
    return;
}
dl c[N][N],f[N][N],x[N],ans;
inline void Gauss(int n,int m){
    for(int i=1;i<=n;i++){
    int l=i;
    for(int j=l+1;j<=n;j++)
        if(fabs(f[l][i])<fabs(f[j][i]))l=j;
    if(l!=i)
        for(int j=i;j<=m;j++)
        swap(f[l][j],f[i][j]);
    for(int j=i+1;j<=n;j++){
        dl temp=f[j][i]/f[i][i];
        for(int k=i;k<=m;k++)
        f[j][k]=f[j][k]-f[i][k]*temp;
    }
    }
    for(int i=n;i>=1;i--){
    dl t=f[i][m];
    for(int j=n;j>i;j--)
        t-=x[j]*f[i][j];
    x[i]=t/f[i][i];
    }
    return ;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
    int u,v,w;
    scanf("%d%d%d",&u,&v,&w);
    add(u,v,w);
    if(u!=v)add(v,u,w);
    }
    for(int i=0;i<=30;i++){
    memset(f,0,sizeof(f));
    memset(x,0,sizeof(x));
    for(int u=1;u<n;u++){
        for(int k=head[u];k;k=e[k].nxt){
        int v=e[k].to,w=e[k].w;
        if(w&(1<<i))f[u][v]+=1,f[u][n+1]+=1;
        else f[u][v]-=1;
        }
        f[u][u]+=d[u];
    }
    for(int j=1;j<=n+1;j++)f[n][j]=0;
    f[n][n]=1;
    Gauss(n,n+1);
    ans+=x[1]*(1<<i);
    }
    printf("%.3f
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/luyouqi233/p/8274103.html