BZOJ 2115: [Wc2011] Xor 线性基

Posted Lsxxxxxxxxxxxxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\n", ans);
     return 0;
}

 

以上是关于BZOJ 2115: [Wc2011] Xor 线性基的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2115 [Wc2011] Xor

bzoj2115: [Wc2011] Xor

BZOJ2115:[WC2011]Xor——题解

BZOJ 2115: [Wc2011] Xor 线性基

BZOJ2115 [Wc2011] Xor

Bzoj 2115: [Wc2011] Xor