zoukankan      html  css  js  c++  java
  • BZOJ 2115: [Wc2011] Xor 线性基

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2115


    解法:

    膜:http://www.cnblogs.com/ljh2000-jump/p/5869925.html

    这道题要求从1到n的最大xor和路径,存在重边,允许经过重复点、重复边。那么在图上作图尝试之后就会发现,路径一定是由许多的环和一条从1到n的路径组成。容易发现,来回走是没有任何意义的,因为来回走意味着抵消。考虑这道题求得是路径xor和最大,所以必然我们要想办法处理环的情况。我的做法是任意地先找出一条从1到n的路径,把这条路径上的xor和作为ans初值(先不管为什么可行),然后我们的任务就变成了求若干个环与这个ans初值所能组合成的xor最大值。显然,我们需要预处理出图上所有的环,并处理出所有环的环上xor值,这当然是dfs寻找,到n的路径的时候顺便求一下就可以了。

      当我们得到了若干个环的xor值之后,因为是要求xor最大值,我们就可以构出这所有xor值的线性基。构出之后,再用ans在线性基上取max就可以了。

    为什么可以这么做? 证明在上面大牛博客里有证明。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 50010;
    const int maxm = 200010;
    int n, m, edgecnt;
    int head[maxn];
    bool vis[maxn];
    LL dx[maxn];
    LL p[70];
    LL circle[maxm], ans;
    void init(){
        memset(head, -1, sizeof(head));
        edgecnt = 0;
    }
    struct edge{
        int to,next;
        LL w;
        edge(){}
        edge(int to, int next, LL w):to(to),next(next),w(w){}
    }E[maxm];
    int cnt = 0;
    void add(int u, int v, LL w){
        E[edgecnt].to = v, E[edgecnt].next = head[u], E[edgecnt].w = w, head[u] = edgecnt++;
    }
    void dfsloop(int x){
        vis[x] = 1;
        for(int i=head[x]; i+1; i=E[i].next){
            int to = E[i].to;
            if(!vis[to]) dx[to] = dx[x]^E[i].w, dfsloop(to);
            else{
                circle[++cnt] = dx[to]^dx[x]^E[i].w;
            }
        }
    }
    
    int main()
    {
        int x,y;
        LL z;
        init();
        scanf("%d %d", &n,&m);
        for(int i=1; i<=m; i++){
            scanf("%d %d %lld", &x,&y,&z);
            add(x, y, z);
            add(y, x, z);
        }
        dfsloop(1);
        ans = dx[n];//任取一条从1到n的路径,并得到其xor和
        for(int i=1; i<=cnt; i++){
            for(int j=62; j>=0; j--){
                if(!(circle[i]>>j)) continue;
                if(!p[j]){
                    p[j] = circle[i];
                    break;
                }
                circle[i] ^= p[j];
            }
        }
         //for(int i=62;i>=0;i--) if(!(ans>>i)) ans^=p[i];
         //ans有初值,不能直接根据这一位是否为0来判断是否更大,max更为稳妥
         for(int i=62; i>=0; i--){
            if((ans^p[i])>ans){
                ans = ans^p[i];
            }
         }
         printf("%lld
    ", ans);
         return 0;
    }
    
  • 相关阅读:
    CF1221D Make The Fence Great Again
    HDU.1536.S-Nim(博弈论 Nim)
    HDU.1848.Fibonacci again and again(博弈论 Nim)
    POJ.1704.Georgia and Bob(博弈论 Nim)
    洛谷.2197.nim游戏(博弈论 Nim)
    博弈论基础——巴什博弈
    SPOJ.104.Highways([模板]Matrix Tree定理 生成树计数)
    BZOJ.4289.PA2012 Tax(思路 Dijkstra)
    BZOJ.4753.[JSOI2016]最佳团体(01分数规划 树形背包DP)
    图论
  • 原文地址:https://www.cnblogs.com/spfa/p/7449907.html
Copyright © 2011-2022 走看看