BZOJ 2115 WC2011 Xor 线性基+贪心

4 篇文章 0 订阅
3 篇文章 0 订阅

题目大意:给出一个无向图,求出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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值