您的位置:首页 > 其它

BZOJ 2115 [Wc2011] Xor

2016-07-16 07:53 246 查看
给定边权为非负的无向图,求1到n边权异或和最大的路径(可以重复经过点和边)。

n≤50000,m≤100000,0≤ei≤1018

PoPoQQQ:

http://blog.csdn.net/popoqqq/article/details/39804075

一条路径的异或和可以化为一条1到n的简单路径和一些简单环的异或和,我们首先DFS求出任意一条1到n的简单路径以及图中所有线性无关的环(线性基)。

度娘:

1.线性基能相互异或得到原集合的所有相互异或得到的值。

2.线性基是满足性质1的最小的集合。

3.线性基没有异或和为0的子集。

用高斯消元求线性基,其结果的特点是最高位单调,且每个数的最高位只出现在这个数上。

(e.g 110,011->101,011)

最后贪心求解即可。

线性基+dfs生成树

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
template<class T>void sc(T &x){
int f=1;x=0;char c;
while(c=getchar(),c<48)if(c=='-')f=-1;
do x=x*10+(c^48);
while(c=getchar(),c>47);
x*=f;
}
template<class T>void nt(T x){
if(!x)return;
nt(x/10);
putchar('0'+x%10);
}
template<class T>void pt(T x){
if(x<0){
putchar('-');
x=-x;
}
if(!x)putchar('0');
else nt(x);
}
//----------------------------
const int maxn=50004;
const int maxm=100005;

int n,m;

int last[maxm],ecnt;
struct Edge{
int to;ll w;int nxt;
}edge[maxm<<1];
void ins(int u,int v,ll w){
edge[++ecnt]=(Edge){v,w,last[u]};
last[u]=ecnt;
}

ll d[maxm<<1];//*
ll key[maxn];
int tot;
bool vis[maxn];
void dfs(int x){
vis[x]=true;
for(int i=last[x];i;i=edge[i].nxt){
int y=edge[i].to;
if(vis[y]){
ll t=key[x]^key[y]^edge[i].w;
if(t)d[++tot]=t;
}
else{
key[y]=key[x]^edge[i].w;
dfs(y);
}
}
}
void gospoly(){
int i,k=0;
for(ll t=1ll<<62;t;t>>=1){
for(i=k+1;i<=tot;i++)
if(d[i]&t)break;
if(i>tot)continue;
swap(d[++k],d[i]);
for(int j=1;j<=tot;j++)
if(j!=k&&(d[j]&t))d[j]^=d[k];
}
}

int main(){
sc(n);sc(m);
ll w;
for(int u,v,i=1;i<=m;i++){
sc(u);sc(v);sc(w);
ins(u,v,w);
ins(v,u,w);
}
dfs(1);
gospoly();
ll ans=key
;
for(int i=1;d[i];i++)
if((ans^d[i])>ans)ans^=d[i];
printf("%lld\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: