【题解】HNOI-2011XOR和路径

Problem

洛谷 & bzoj

Solution

可能是第一次两分钟想出HNOI的题

考虑到直接求解异或和很麻烦(如果dalao能直接做当我没说),套路拆分二进制位,对于每一个二进制位单独考虑,则 a n s = t = 2 k E ( n ) t

则如果权值只有0和1,则可以使用最基本的高斯消元求解(和HNOI那道游走差不多),总复杂度 O ( n 3 log 2 m a x v a l )

注意在自环时特判一下,卡卡精度即可

最近题解越写越短了

Code

#include<algorithm>
#include<cctype>
#include<cstdio>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))

template <typename _Tp> inline _Tp read(_Tp&x){
    rg char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}

const int N=102,M=10010;
struct Edge{int v,nxt,w;}a[M<<1];
int head[N],deg[N];
double d[N][N];
int n,m,_,mxt;

inline void add(int u,int v,int w){a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;}

void gauss(){
    for(rg int i=1;i<=n;++i){
        int p=i;
        for(rg int j=i+1;j<=n;++j)if(d[j][i]>d[p][i])p=j;
        if(p!=i)for(rg int j=i;j<=n+1;++j)swap(d[i][j],d[p][j]);
        double t=d[i][i];
        for(rg int j=i;j<=n+1;++j)d[i][j]/=t;
        for(rg int j=1;j<=n;++j)if(j!=i&&d[j][i]!=0){
            t=d[j][i];
            for(rg int k=i;k<=n+1;++k)d[j][k]-=t*d[i][k];
        }
    }return ;
}

int main(){
    read(n),read(m);
    for(rg int i=0,x,y,z;i<m;++i){
        read(x),read(y),read(z);add(x,y,z),++deg[x];
        if(x!=y)add(y,x,z),++deg[y];
        mxt=max(mxt,z);
    }
    double Ans(0);
    for(rg int t=1;t<=mxt;t<<=1){
        for(rg int i=1;i<=n;++i)
        for(rg int j=1;j<=n+1;++j)d[i][j]=0;
        d[n][n]=1;
        for(rg int x=1;x<n;++x){
            d[x][x]=deg[x];
            for(rg int i=head[x];i;i=a[i].nxt)
                if(a[i].w&t)++d[x][a[i].v],++d[x][n+1];
                else --d[x][a[i].v];
        }
        gauss();
        Ans+=1.0*d[1][n+1]*t;
    }
    printf("%.3lf\n",Ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40515553/article/details/80386479