标签:Xor int 路径 long 两条 异或 include 2115 BZOJ
Solution
我们可以先算出一条路径的异或和。
首先我们可以证明所有的环都是可以取的。首先从 \(1\) 走到环,再走回去,中间的路径异或和会正好被消去。
其次这样做是对的。两条从起点到终点的路径必定会形成一个环,无论两条路径是否有重合部分,异或一下这个环就能获得这个路径。
有一个没搞懂的地方:环的个数要开 \(M*2\) 才能过,以后还是开容器吧 \(QWQ\)。
Code
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 5e4 + 5;
int tot, cnt, n, m, head[N], nxt[N << 2], dot[N << 2];
ll val[N << 2], loop[N << 2], s[N], d[65];
bool vis[N];
ll read() {
ll x = 0, f = 1; char s;
while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
return x * f;
}
void addEdge(const int u, const int v, const ll w) {
nxt[++ cnt] = head[u], dot[cnt] = v, head[u] = cnt, val[cnt] = w;
}
void dfs(const int u) {
vis[u] = 1;
for(int i = head[u]; i; i = nxt[i]) {
int v = dot[i];
if(vis[v]) loop[++ tot] = s[u] ^ s[v] ^ val[i];
else s[v] = s[u] ^ val[i], dfs(v);
}
}
void ins(ll x) {
for(int i = 62; ~i; -- i)
if(x & (1ll << i)) {
if(! d[i]) {d[i] = x; return;}
else x ^= d[i];
}
}
ll Max(ll x) {
for(int i = 62; ~i; -- i) x = max(x, x ^ d[i]);
return x;
}
int main() {
int u, v; ll w;
while(~ scanf("%d %d", &n, &m)) {
tot = cnt = 0;
memset(vis, 0, sizeof vis);
memset(head, 0, sizeof head);
memset(s, 0, sizeof s);
memset(d, 0, sizeof d);
for(int i = 1; i <= m; ++ i) {
u = read(), v = read(), w = read();
addEdge(u, v, w); addEdge(v, u, w);
}
dfs(1);
for(int i = 1; i <= tot; ++ i) ins(loop[i]);
printf("%lld\n", Max(s[n]));
}
return 0;
}
标签:Xor,int,路径,long,两条,异或,include,2115,BZOJ 来源: https://www.cnblogs.com/AWhiteWall/p/12870102.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。