bzoj2115[Wc2011] Xor 线性基

题目大意

传送门

给定一个无向图,n点m边,求从1到n的所有路径中异或和最大的那条

分析

线性基神题啊(可能是我弱)
先随便搞一条路径。
从固定点到另外一个固定点的两条不相交路径异或值显然可以构成一个环的路径异或值。路径1^路径2=环
我们把它换一下:路径1=环^路径2
所以最优路径=初始路径^环1^环2……
那么我们搜索出每个环的异或值,问题就转化为求一个数和一堆数的最大异或和。
可以用线性基来搞。

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 55000;
const int M = 220000;
long long read() {
    char ch = getchar(); long long x = 0;
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
    return x;
}
long long bin[70], dis[N], w[M], d[1100000], a[70];
int to[M], pre[N], nxt[M], top, cnt, n, m; bool vis[N];
void add(int u, int v, long long ww) {to[++top] = v; nxt[top] = pre[u]; w[top] = ww; pre[u] = top;}
void adds(int u, int v, long long w) {add(u, v, w); add(v, u, w);}
void dfs(int u) {
    vis[u] = 1;
    for(int i = pre[u]; i; i = nxt[i]) 
    if(!vis[to[i]]) {dis[to[i]] = dis[u] ^ w[i]; dfs(to[i]);}
    else d[++cnt] = dis[to[i]] ^ w[i] ^ dis[u];

}
void Insert(long long x) {
    for(int i = 63; ~i && x; --i)
    if(bin[i] & x)
        a[i] = !a[i] ? x : a[i], x ^= a[i];
}
long long Query_max(long long ans) {for(int i = 63; ~i; --i) ans = !(ans & bin[i]) ? ans ^ a[i] : ans; return ans;}

int main() {
    bin[0] = 1; for(int i = 1;i <= 63; ++i) bin[i] = bin[i - 1] << 1;
    n = read(); m = read();
    while(m--) {int u = read(), v = read(); long long w = read(); adds(u, v, w);}
    dfs(1);
    for(int i = 1;i <= cnt; ++i) Insert(d[i]);
    printf("%lld\n", Query_max(dis[n]));
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值