BZOJ 2115 WC2011 Xor 线性基+贪心

题目大意:给出一个无向图,求出1~N的最长xor路径。


思路:先求出一条任意的1~N的路径的xor和,之后算出所有的简单环中的异或和。注意到异或的一个很好的性质——x^y^x=y,也就是说对于每个简单环我们若是想走完这个环只需要把这个环的异或和异或到原路径上的异或和就行了。

于是问题就转化成了一个数字和一些数字的最大异或和。求出那些环的异或和的线性基,然后利用贪心的思想逐位确定所有位置的情况,最后就是最大的答案了。


CODE:

#define _CRT_SECURE_NO_WARNINGS

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 200010
using namespace std;

int points,edges;
int head[MAX],total;
int _next[MAX],aim[MAX];
long long length[MAX];

inline void Add(int x,int y,long long len)
{
	_next[++total] = head[x];
	aim[total] = y;
	length[total] = len;
	head[x] = total;
}

long long BFS()
{
	static bool v[MAX];
	static int from[MAX];
	static long long len[MAX];
	static queue<int> q;
	q.push(1);
	v[1] = true;
	while(!q.empty()) {
		int x = q.front(); q.pop();
		if(x == points) {
			long long re = 0;
			for(int i = points; i != 1; i = from[i])
				re ^= len[i];
			return re;
		}
		for(int i = head[x]; i; i = _next[i])
			if(!v[aim[i]]) {
				v[aim[i]] = true;
				from[aim[i]] = x;
				len[aim[i]] = length[i];
				q.push(aim[i]);
			}
	}
	return 0;
}

long long _xor[MAX << 2];
int xors;

void DFS(int x)
{
	static bool v[MAX];
	static long long last[MAX];
	v[x] = true;
	for(int i = head[x]; i; i = _next[i]) {
		if(v[aim[i]])
			_xor[++xors] = last[aim[i]]^last[x]^length[i];
		else {
			last[aim[i]] = last[x]^length[i];
			DFS(aim[i]);
		}
	}
}

long long base[110];

void LinearBase()
{
	for(int i = 1; i <= xors; ++i)
		for(int j = 63; ~j; --j)
			if((_xor[i] >> j)&1) {
				if(!base[j]) {
					base[j] = _xor[i];
					break;
				}
				else	_xor[i] ^= base[j];
			}
}

long long z;

int main()
{
	cin >> points >> edges;
	for(int x,y,i = 1; i <= edges; ++i) {
		scanf("%d%d%lld",&x,&y,&z);
		Add(x,y,z),Add(y,x,z);
	}
	long long xor_length = BFS();
	DFS(1);
	LinearBase();
	for(int i = 63; ~i; --i)
		if(!((xor_length >> i)&1))
			xor_length ^= base[i];
	cout << xor_length << endl;
	return 0;
}


你可能感兴趣的:(高斯消元,贪心,bzoj,线性基,Wc2011)