2115: [Wc2011] Xor
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 4344 Solved: 1812
[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
sol:
求从1到n的路径的最大xor值。考虑这道题是一张无向图,不是很好做。假设这题是一颗树,求任意两点间的路径的最大xor值,我们指定1为根,记f[i]为1到i的xor值,那么i到j的路径xor就是f[i]^fj。考虑把这个结论推广到图上。我们先把原图选出一些边做一个生成树出来。那么i到j的xor值在树上是唯一的,但是这个树外还有一些边,和树边一起构成了一些环,如果我们经过了一些非树边,然后到达树上的一个节点,这时候的xor值怎么表示呢?画图容易发现,i到j的xor值就是i到j在树上的xor值 xor上经过的非树边和树边形成的环(这个描述不清楚,如果有动手画图应该明白我什么意思)。那么这题就很清晰了,我们先建一个生成树,求1到n的xor值(记作ans),然后还有一些环,我们可以经过这些环(因为我从任何一个点,都可以走到一个环上,然后再走回这个点,所以环的值总能被取到),最大化这个ans xor 环的价值。上线性基贪心即可,如果ans的某一位为0,xor上对应的基。
我好像不会求环的值?假的,每条非树边都对应了一个环,随便搞即可。
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
typedef double s64;
int n,m;
inline int read()
{
char c;
int res,flag=0;
while((c=getchar())>'9'||c<'0') if(c=='-')flag=1;
res=c-'0';
while((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+c-'0';
return flag?-res:res;
}
const int N=110000;
struct cc
{
int x,y;
ll z;
}e[N];
int top,father[N];
ll f[N],val[N];
int fir[N],nex[N],go[N],tot;
inline void add(int x,int y,ll z)
{
nex[++tot]=fir[x];fir[x]=tot;go[tot]=y;val[tot]=z;
nex[++tot]=fir[y];fir[y]=tot;go[tot]=x;val[tot]=z;
}
inline int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
inline bool unit(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
{
father[fy]=fx;
return 1;
}
return 0;
}
inline void dfs(int u,int fa)
{
int e,v;
for(e=fir[u];v=go[e],e;e=nex[e])
if(v!=fa)
{
f[v]=f[u]^val[e];
dfs(v,u);
}
}
ll c[N];
int b[N];
int main()
{
// freopen("2115.in","r",stdin);
// freopen(".out","w",stdout);
n=read();
m=read();
for(int i=1;i<=n;++i) father[i]=i;
for(int i=1;i<=m;++i)
{
int x,y;ll z;
x=read();
y=read();
scanf("%lld",&z);
if(unit(x,y)) add(x,y,z);
else e[++top]=(cc){x,y,z};
}
dfs(1,1);
for(int i=1;i<=top;++i)
c[i]=f[e[i].x]^f[e[i].y]^e[i].z;
ll ans=f[n];
for(int i=1;i<=top;++i)
{
int fir=-1;
for(int j=60;j>=0;--j)
if((c[i]>>j)&1)
{
if(b[j]) c[i]^=c[b[j]];
else fir=max(fir,j);
}
if(fir!=-1)
{
for(int j=60;j>=0;--j)
if(b[j]&&((c[b[j]]>>fir)&1))
c[b[j]]^=c[i];
b[fir]=i;
}
}
for(int j=60;j>=0;--j)
if(!(ans>>j&1))
ans^=c[b[j]];
cout<<ans;
}
1A美滋滋