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;
    }

     

  • 相关阅读:
    Balance的数学思想构造辅助函数
    1663. Smallest String With A Given Numeric Value (M)
    1680. Concatenation of Consecutive Binary Numbers (M)
    1631. Path With Minimum Effort (M)
    1437. Check If All 1's Are at Least Length K Places Away (E)
    1329. Sort the Matrix Diagonally (M)
    1657. Determine if Two Strings Are Close (M)
    1673. Find the Most Competitive Subsequence (M)
    1641. Count Sorted Vowel Strings (M)
    1679. Max Number of K-Sum Pairs (M)
  • 原文地址:https://www.cnblogs.com/cytus/p/9580435.html
Copyright © 2011-2022 走看看