ACwing.228 异或(线性基)
题目:
- 给一张图,让你找一条1到n的路径,可以重复走边和点,问路径权值异或和最大是多少。
题解:
- 基本思路就是对每条路径把路径上的环的权值异或和放进线性基,因为环要走就走全部一次,走两次会异或掉。所以我们dfs找环,把环放进一个线性基,最后把1到n的简单路径异或和放进去,如果1到n有多个路径,就有环dfs就放进线性基中了,所以求最大值就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<fstream>
using namespace std;
typedef long long ll;
const int N = 5e4 + 105;
const int mod = 10000;
const int P = 9999;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
inline int read() {
char ch = getchar(); int x = 0, f = 1;
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while ('0' <= ch && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
} return x * f;
}
//线性基
const int maxbit = 62; //maxbit不能太大
struct L_B{
ll lba[maxbit];
int cnt;
L_B(){
memset(lba, 0, sizeof(lba));
cnt = 0;
}
void Insert(ll val){ //插入
for(int i = maxbit - 1; i >= 0; -- i)
if(val & (1ll << i)){
if(!lba[i]){
lba[i] = val;
break;
}
val ^= lba[i];
}
}
ll query_max(ll x){ //查找最大值
ll res = x;
for(int i = maxbit - 1; i >= 0; -- i){
ll che = res ^ lba[i];
if(che > res) res^=lba[i];
}
return res;
}
};
//图论基本模板
struct Edge{
int to;
ll c;
int nxt;
}edge[N * 4];
int head[N], cnt = 0;
int n, m;
inline void add(int u, int v, ll w){
edge[cnt].to = v;
edge[cnt].c = w;
edge[cnt].nxt = head[u];
head[u] = cnt ++;
}
//main()
ll res;
int vis[N];
L_B lb;
ll dis[N];
void dfs(int u, int pre){
vis[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].nxt){
int v = edge[i].to;
ll w = edge[i].c;
if(v == pre) continue;
if(vis[v]){
lb.Insert(w ^ dis[u] ^ dis[v]);
continue;
}
dis[v] = dis[u] ^ w;
dfs(v, u);
}
}
int main()
{
scanf("%d%d",&n,&m);
memset(head, -1, sizeof(head));
for(int i = 1; i <= m; ++ i){
int x, y;
ll w;
scanf("%d%d%lld",&x,&y,&w);
add(x, y, w);
add(y, x, w);
}
dfs(1, -1);
printf("%lld\n",lb.query_max(dis[n]));
return 0;
}