2115: [Wc2011] Xor
Time Limit: 10 Sec Memory Limit: 259 MB
Description
Input
第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。
Output
仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。
Sample Input
5 7
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2
Sample Output
6
HINT
Source
题解:
整个1->n的过程就是 一堆环和一条简单路径的异或和
任意环的异或和 任意组合起来,这个可以高斯消元求解,偷个懒利用线性基也是可以的
15年ccpc南阳与这个题做法相同,,算是双倍经验题:传送门
#include<bits/stdc++.h>
using namespace std;
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
typedef unsigned long long ULL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N=5e5+,M=1e6+,inf=; LL dep[N],a[N],ins[N],ans;
int n,m,vis[N],cnt,t = ,head[N],has[N];
struct ss {
int to,next,id;
LL c;
}e[N * ];
void add(int u,int v,LL w,int id) {
e[t].next = head[u];
e[t].to = v;
e[t].c = w;
e[t].id = id;
head[u] = t++;
}
void dfs(int u,int f) {
vis[u] = vis[f] + ;
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(has[e[i].id] || (vis[to] && vis[to] < vis[u])) continue;
if(vis[to]) {
a[++cnt] = dep[to] ^ dep[u] ^ e[i].c;
continue;
}
has[e[i].id] = ;
dep[to] = dep[u] ^ e[i].c;
dfs(to,u);
}
}
void go(int u,LL now) {
if(u == n) {
LL ret = now;
for(int i = ; i >= ; --i)
if((ins[i]^ret) > ret) ret^=ins[i];
ans = max(ans,ret);
return ;
}
vis[u] = ;
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if(has[e[i].id]) continue;
has[e[i].id] = ;
go(to,now^e[i].c);
}
vis[u] = ;
}
int main() {
scanf("%d%d",&n,&m);
for(int i = ; i <= m; ++i) {
int x,y;LL z;
scanf("%d%d%lld",&x,&y,&z);
if(x == y) {
a[++cnt] = z;
continue;
}
add(x,y,z,i),add(y,x,z,i);
}
dfs(,);
for(int i = ; i <= cnt; ++i) {
for(int j = ; j >= ; --j) {
if(a[i]&(1LL<<j)) {
if(!ins[j]) {
ins[j] = a[i];
break;
}
a[i] ^= ins[j];
}
}
}
ans = ;
memset(vis,,sizeof(vis));
memset(has,,sizeof(has));
go(,);
cout<<ans<<endl;
return ;
}