• BZOJ 2115: [Wc2011] Xor


    题面

    解题思路

    因为异或一个数两次相当于这个数不变,思考可能经过的路径,分为两部分,一部分是简单路径,就是直接到n的路径,还有就是环,如果这个环与简单路径间接相连,我们可以直接把环的贡献异或,因为可以先到环转一圈回去,中间的路径经过两次相当于没经过。考虑到状态比较多,我们考虑线性基,dfs找到环与路径,遇到环插入线性基,最后贪心找最大。

    代码

    #include<iostream>
    #include<cstdio>
    #define LL long long
    
    using namespace std;
    const int MAXN = 50005;
    
    inline LL rd(){
        LL x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-48;ch=getchar();}
        return x*f;
    }
    
    struct Edge{
        LL nxt,to;
        LL w;
    }edge[MAXN<<2];
    
    LL n,m;
    int head[MAXN],cnt;
    LL ans,b[70],dis[MAXN];
    bool vis[MAXN];
    
    inline void add(LL bg,LL ed,LL v){
        edge[++cnt].to=ed;
        edge[cnt].w=v;
        edge[cnt].nxt=head[bg];
        head[bg]=cnt;
    }
    
    inline void insert(LL x){
        for(register int i=63;~i;i--)
            if(x&(1ll<<i)){
                if(!b[i]) {b[i]=x;break;}
                else x^=b[i];
            }
    }
    
    inline void dfs(int x){
        vis[x]=1;
        for(register LL i=head[x];i;i=edge[i].nxt){
            LL u=edge[i].to;
            if(vis[u]) insert(dis[x]^dis[u]^edge[i].w);
            else dis[u]=dis[x]^edge[i].w,dfs(u);
        }
    }
    
    int main(){
        n=rd();m=rd();
        for(register LL i=1;i<=m;i++){
            LL x,y,z;
            x=rd();y=rd();z=rd();
            add(x,y,z);add(y,x,z);
        }
        dfs(1);
        ans=dis[n];
    //  cout<<ans<<endl;
        for(register int i=63;i>=0;i--)
            if((ans^b[i])>ans) ans^=b[i];
        printf("%lld",ans);
    }
  • 相关阅读:
    Cookie练习
    JS写九九乘法表
    对GridView实现分页
    对GridView的行加颜色并弹出Kindeditor
    对Dictionary的理解
    一、android 开发环境大搭建
    main方法的测试
    main 方法的书写(1)
    由InvocationTargetException引发的思考
    汇编学习笔记之处理器体系结构
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676996.html
Copyright © 2020-2023  润新知