BZOJ 2115([Wc2011] Xor-线性基求法)

2115: [Wc2011] Xor

Time Limit: 10 Sec   Memory Limit: 259 MB
Submit: 465   Solved: 210
[ 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

 

Source

[ Submit][ Status][ Discuss]




线性基。。。(经典?)应用

考虑所有路径。。。

实际上就是一条Xor一堆环

环在dfs中顺带求出。。。

得到[环的集合]

由于

A xor B=C

A xor C=B

所有把B换成C不影响结果。。。

让我们弄出所有线性基。。这样做的好处是最高位为1的只有1个

贪心Xor 吧....

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#include<cmath>
#include<cctype>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define RepD(i,n) for(int i=n;i>=0;i--)
#define MEM(a) memset(a,0,sizeof(a))
#define MEMI(a) memset(a,127,sizeof(a))
#define MEMi(a) memset(a,128,sizeof(a))
#define MAXN (50000+10)
#define MAXM (2*100000+10)
int n,m;
int edge[MAXM],pre[MAXN]={0},next[MAXM]={0};
long long weight[MAXM],size=0;
void addedge(int u,int v,long long w)
{
	edge[++size]=v;
	weight[size]=w;
	next[size]=pre[u];
	pre[u]=size;
}
bool b[MAXN]={0};
long long d[MAXN]={0};
long long a[MAXN+MAXM],a_n=0;
void dfs(int x)
{
	b[x]=1;
	Forp(x)
	{
		int &v=edge[p];
		if (!b[v]) 
		{
			d[v]=d[x]^weight[p];
			dfs(v);
		}else a[++a_n]=d[x]^d[v]^weight[p];
	}
	//b[x]=0;
}
int gauss_lb()
{
	int k=1;
	ForD(i,64)
	{
		int t=0;
		Fork(j,k,a_n) if ((a[j]>>i-1)&1) t=j;
		if (!t) continue;
		swap(a[k],a[t]);
		Fork(j,k+1,a_n) if ((a[j]>>i-1)&1) a[j]^=a[k];
		k++;	
	}
	return --k;
}
int main()
{
//	freopen("bzoj2115.in","r",stdin);
//	freopen(".out","w",stdout);
	scanf("%d%d",&n,&m);
	For(i,m)
	{
		int u,v;long long w;
		cin>>u>>v>>w;
		//cout<<u<<' '<<v<<' '<<w<<endl;
		addedge(u,v,w);addedge(v,u,w);
	}
	dfs(1);
	long long ans=d[n];
	int tot=gauss_lb();
	For(i,tot)
	{
		ans=max(ans,ans^a[i]);
	}
	cout<<ans<<endl;
	return 0;
}

最近装完CB和Linux后%lld不能用了啊杯具。。。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值