zoukankan      html  css  js  c++  java
  • Evanyou Blog 彩带

      题目传送门

    最大XOR和路径

    格式难调,题面就不放了。


      分析:

      一道需要深刻理解线性基的题目。

      好久没打过线性基的题了,一开始看到这题还是有点蒙逼的,想了几种方法全被否定了。还是看了大佬的题解才会做的。

      首先我们能想到,在图中从$1$走到$n$有这么两种情况,一种是一条链直接走到$n$,另一种是先走链然后绕若干个环然后回到链上走到$n$。对于这道题显然我们是要考虑所有的环的(由异或的性质可知)。

      然后我们又可以发现,如果一条链和一个环中间有一条路径相连,那么我们从链上走到环上时会经过这条路径一次,从环上回到链上时又会走这条路径一次,那么两次走过的路径异或和就是$0$!

      再看,如果从$1$走到$n$有若干条链,那么这些链会相互构成若干个环,如果我们走了一条链,然后让这条链异或这些环,就可以得到对应的另一条链!(可以自己画图分析一下,博主太懒不想画图_(:з」∠)_)

      综合一下上面的性质,我们就能得到一种算法:进行一遍$DFS$,把所有的环构造成线性基,然后把任意一条从$1$到$n$的链放入线性基中求最大异或和。

      $SO$,这道黑题就这么过了。

      博主手残写了个$namespace$,不过好像跑得还挺快。

      Code:

    //It is made by HolseLee on 3rd Sep 2018
    //Luogu.org P4151
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cmath>
    #include<iostream>
    #include<iomanip>
    #include<algorithm>
    using namespace std;
    
    typedef long long ll;
    const int N=5e4+7,M=2e5+7;;
    int n,m,head[N],cnte;
    ll dis[N],b[70];
    bool vis[N];
    struct Node {
        int to,nxt; ll val;
        
        Node() {}
        Node(int _to,ll _val,int _nxt): to(_to),val(_val),nxt(_nxt) {}
    }e[M];
    
    namespace LinerBase {
        void insert(ll x)
        {
            for(int i=63; i>=0; --i) {
                if( !(x>>i) ) continue;
                if( !b[i] ) {
                    b[i]=x; break;
                } else {
                    x^=b[i];
                }
            }
        }
    
        ll quary(ll x)
        {
            ll ret=x;
            for(int i=63; i>=0; --i) {
                if( (ret^b[i])>ret ) ret^=b[i];
            }
            return ret;
        }
    }
    
    inline ll read()
    {
        char ch=getchar(); ll num=0; bool flag=false;
        while( ch<'0' || ch>'9' ) {
            if( ch=='-' ) flag=true;
            ch=getchar();
        }
        while( ch>='0' && ch<='9' ) {
            num=num*10+ch-'0';
            ch=getchar();
        }
        return flag ? -num : num;
    }
    
    inline void add(int x,int y,ll z)
    {
        e[++cnte]=Node(y,z,head[x]);
        head[x]=cnte;
    }
    
    void dfs(int x,ll now)
    {
        dis[x]=now, vis[x]=true;
        for(int i=head[x]; i; i=e[i].nxt) {
            if(!vis[e[i].to]) dfs(e[i].to,now^e[i].val);
            else LinerBase::insert(now^e[i].val^dis[e[i].to]);
        }
    }
    
    int main()
    {
        n=read(); m=read();
        int x,y;ll z;
        for(int i=1; i<=m; ++i) {
            x=read(), y=read(), z=read();
            add(x,y,z); add(y,x,z);
        }
        dfs(1,0);
        printf("%lld
    ",LinerBase::quary(dis[n]));
        return 0;
    }

     

  • 相关阅读:
    es5和es6的区别
    如何将word文档内容在网页显示方法
    实现在线浏览PDF文件的方法
    移动端开发兼容问题
    常见的浏览器兼容问题和解决方法
    弹层
    猜数字游戏
    米字格画布
    时钟制作
    关于屏幕高度
  • 原文地址:https://www.cnblogs.com/cytus/p/9580435.html
Copyright © 2011-2022 走看看