bzoj2115 Xor

题目链接

problem

考虑一个边权为非负整数的无向连通图,节点编号为\(1\)\(N\),试求出一条从 \(1\) 号节点到 \(N\) 号节点的路径,使得路径上经过的边的权值的 \(XOR\) 和最大。

路径可以重复经过某些点或边,当一条边在路径中出现了多次时,其权值在计算 \(XOR\) 和时也要被计算相应多的次数,具体见样例。

solution

考虑先确定一条从\(1\)\(n\)的不含环的路径。

enter description here

如图,我们先选择\(1-2-3-4-9-10\)这条路径,然后发现,我们在3这个位置可以通过\(3-5\)这条边,去环里面转一圈,然后再回来。因为\(3-5\)这条边走了两边。所以增加的边权就是这个环的异或和。

这个我们就可以猜想了。我们先选择任意一个可以从\(1-n\)的路径,称之为链。然后该图中所有的环都是可以产生贡献的。所以我们把这条链的异或和和各个环的异或和全部扔到线性基里去。然后求最大值就行了。

为什么这条链可以任意选呢。因为如果有其他的路径可以到达\(n\),必定与该链形成了环。只要选择那个环就相当于走了另外一条路径。

如图

enter description here

我们可以选择以\(1-2-3-4-9-10\)或者是\(1-2-3-4-11-12-13-9-10\)作为链。
不管以哪一条为链只要异或上这个蓝色的环。就会变成另外一条链。

code

/*
* @Author: wxyww
* @Date:   2019-07-23 14:59:35
* @Last Modified time: 2019-07-23 15:09:13
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int N = 100100;
#define int ll
ll read() {
    ll x=0,f=1;char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
struct node {
    int v,nxt;ll w;
}e[N << 1];
int head[N],ejs;
void add(int u,int v,int w) {
    e[++ejs].v = v;e[ejs].w = w;e[ejs].nxt = head[u];head[u] = ejs;
}
int vis[N];
ll dis[N],p[N];
void ins(ll x) {
    for(int i = 63;i >= 0;--i) {
        if(!(x >> i & 1)) continue;
        if(!p[i]) {
            p[i] = x;break;
        }
        else x ^= p[i];
    }
}
ll query(ll x) {
    ll ans = x;
    for(int i = 63;i >= 0;--i) if((ans ^ p[i]) > ans) ans ^= p[i];
    return ans;
}
void dfs(int u,int father) {
    vis[u] = 1;;
    for(int i = head[u];i;i = e[i].nxt) {
        int v = e[i].v;
        if(v == father) continue;
        if(vis[v]) {
            ins(dis[u] ^ e[i].w ^ dis[v]);continue;
        }
        else dis[v] = dis[u] ^ e[i].w,dfs(v,u);
    }
}

 main() {
    int n = read(),m = read();
    for(int i = 1;i <= m;++i) {
        int u = read(),v = read();ll w = read();
        add(u,v,w);add(v,u,w);
    }
    dfs(1,0);
    cout<<query(dis[n]);
    return 0;
}
posted @ 2019-07-23 16:46 wxyww 阅读(...) 评论(...) 编辑 收藏