码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ 2115】 [Wc2011] Xor

时间:2015-01-28 09:49:06      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:oi   bzoj   xor   高斯消元   

2115: [Wc2011] Xor

Time Limit: 10 Sec  Memory Limit: 259 MB
Submit: 962  Solved: 441
[Submit][Status]

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

技术分享


高斯消元。


这道题可以说非常好的利用了异或的性质:a^b^b=a


做法是随便找一条1-n的路径的异或和,然后选择一些环再与这条路径异或,求最大异或值。


为什么可以这样做?


如果某个环有边在这条路径上,那么异或这个环,环上在路径上的边异或了两次,抵消掉了;

如果某个环没有边这条路径上,因为图是连通的,我们从当前的路径走到那个环上一点,走完整个环,再原路返回,路上的权值异或了两次,被抵消掉了。


因此,只要找那些环与这条路径的异或和最大就可以了。


假设我们现在已经求出了每一个环的异或和,怎么求最大?


对所有环进行高斯消元就行了,具体见【bzoj 2844】


那么如何求出每一个环的异或和?


一次dfs就可以实现了,d[i]表示从1-i路径上的异或和。


如果x子节点y被访问过,那么当前一定构成了环。


根据a^b^b=a的性质,这个环的异或和就是d[x]^d[y]^e[k].v  (e[k].v是连接xy的边权)


#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#define LL long long
using namespace std;
int v[100005],cnt=0,tot=0,n,m,h[100005];
LL c[500005],d[100005];
struct edge
{
	int x,y,ne;
	LL v;
}e[500005];
void Addedge(int x,int y,LL v)
{
	tot++;
	e[tot].x=x;
	e[tot].y=y;
	e[tot].ne=h[x];
	e[tot].v=v;
	h[x]=tot;
}
void dfs(int x)
{
	v[x]=1;
	for (int i=h[x];i;i=e[i].ne)
	{
		int y=e[i].y;
		if (!v[y])
		{
			d[y]=d[x]^e[i].v;
			dfs(y);
		}
		else
		{
			LL k=d[y]^d[x]^e[i].v;
			if (k) c[++cnt]=k;
		}
	}
}
LL Gauss()
{
	LL ans=0LL;
	int now=1;
	for (int i=60;i>=0;i--)
	{
		if (now>cnt) break;
		for (int k=now;k<=cnt;k++)
			if (c[k]&(1LL<<(LL)i))
			{
				swap(c[now],c[k]);
		        for (int j=1;j<=cnt;j++)
					if (j!=now&&(c[j]&(1LL<<(LL)i)))
						c[j]^=c[now];
				now++;
				break;
			}
	}
	ans=d[n];
	for (int i=1;i<=cnt;i++)
		if ((ans^c[i])>ans) ans^=c[i];
	return ans;
}
int main()
{
        scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		int x,y;
		LL v;
		scanf("%d%d%lld",&x,&y,&v);
		Addedge(x,y,v);
		Addedge(y,x,v);
	}
	dfs(1);
	cout<<Gauss()<<endl;
	return 0;
}

技术分享


感悟:

1.一开始wa了多次,因为我把d[n]也高斯消元了,而d[n]是必须要得!


2.xor的性质a^b^b=a!!!


【BZOJ 2115】 [Wc2011] Xor

标签:oi   bzoj   xor   高斯消元   

原文地址:http://blog.csdn.net/regina8023/article/details/43206133

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!