BZOJ 2115 [Wc2011] Xor 线性基+图论

来源:互联网 发布:java撤销 编辑:程序博客网 时间:2024/05/16 18:13

2115: [Wc2011] Xor

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 3840  Solved: 1605
[Submit][Status][Discuss]

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

Sample Output

6

HINT



图上任意一条路径可以表示为其余任意一条首尾相同的路径加上图中的环。

可以看做在出发前,走相同的一条路径走到环绕一圈再回来。这样,异或和就多了环上的一圈。

有了这个定理之后,求出任意一条路径的异或和x,和图上所有环的异或和。求x和所有环的异或和异或最大值即可。


#include <cstdio>#include <iostream>#include <string.h>#include <string> #include <map>#include <queue>#include <deque>#include <vector>#include <set>#include <algorithm>#include <math.h>#include <cmath>#include <stack>#include <iomanip>#define mem0(a) memset(a,0,sizeof(a))#define meminf(a) memset(a,0x3f,sizeof(a))using namespace std;typedef long long ll;typedef long double ld;typedef double db;const int maxn=100005,maxk=63,inf=0x3f3f3f3f;  const ll llinf=0x3f3f3f3f3f3f3f3f;   const ld pi=acos(-1.0L);int head[maxn];ll c[maxn*4],x[maxn],v[maxn];bool visit[maxn];int num=0,cm=0;struct Edge {int from,to,pre;ll dist;};Edge edge[maxn*2];void addedge(int from,int to,ll dist) {edge[num]=(Edge){from,to,head[from],dist};head[from]=num++;edge[num]=(Edge){to,from,head[to],dist};head[to]=num++;}void dfs(int now,ll k) {visit[now]=1;v[now]=k;for (int i=head[now];i!=-1;i=edge[i].pre) {int to=edge[i].to;if (!visit[to]) dfs(to,k^edge[i].dist);else c[++cm]=k^edge[i].dist^v[to];}}bool linear_basis_insert(ll p) {for (int i=maxk;i>=0;i--) {if ((p>>i)%2==1) {if (!x[i]) {x[i]=p;for (int j=i-1;j>=0;j--) if (x[j]&&((x[i]>>j)%2==1)) x[i]^=x[j];                for (int j=i+1;j<=maxk;j++) if ((x[j]>>i)%2==1) x[j]^=x[i];return true;} else p=p^x[i];}}return p!=0;}int main() {int n,m,i,j,z,y;ll d;scanf("%d%d",&n,&m);memset(head,-1,sizeof(head));for (i=1;i<=m;i++) {scanf("%d%d%lld",&z,&y,&d);addedge(z,y,d);}mem0(visit);dfs(1,0);mem0(x);for (i=1;i<=cm;i++) linear_basis_insert(c[i]);ll ans=v[n];for (i=maxk;i>=0;i--) if ((x[i]^ans)>ans) ans^=x[i];printf("%lld\n",ans);return 0;}



原创粉丝点击