【题解】WC-2011最大XOR和路径

Problem

bzoj & 洛谷

Thought

本想像游走那题一样如spfa暴力更新每一个点的线性基,但那样的复杂度十分玄学,个人认为用来骗分还是有点用的

Solution

考虑到对于一条从1到n的路径一定是由一条从1到n的简单路径加上若干个环组成,所以可以预处理处图中的环(不一定要将所有环处理,因为两个相交的小环异或起来可以替代这两个环合起来的大环),可以用 O ( n + m ) 的时间处理

将所有的环的权值异或和放进线性基里
将从1到n的任意一条路径权值异或和作为初始值(因为若有另一条更优的路径,则这两条路径构成一个环,而这个环已经在线性基里了)
求这个初始值在这个线性基里能取到的最大值

Code

#include<cctype>
#include<cstdio>
using namespace std;
typedef long long ll;
#define rg register

template <typename _Tp> inline _Tp read(_Tp&x){
    rg char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}

const int N=50100,M=62;
struct Edge{int v,nxt;ll w;}a[N<<2];
int head[N];ll dis[N],b[N<<2],t[M+10];
char vis[N];
int n,m,_,tot;

inline void add(int u,int v,ll w){a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;}

void dfs(int x){
    vis[x]=1;
    for(int i=head[x];i;i=a[i].nxt)
        if(vis[a[i].v])b[++tot]=dis[x]^dis[a[i].v]^a[i].w;
        else {dis[a[i].v]=dis[x]^a[i].w;dfs(a[i].v);}
    return ;
}

int main(){
    read(n);read(m);
    int x,y;ll z;
    for(rg int i=0;i<m;++i)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
    dfs(1);
    for(rg int i=1;i<=tot;++i)
        for(rg int j=M;~j;--j)
            if((b[i]>>j)&1)
                if(t[j])b[i]^=t[j];
                else {t[j]=b[i];break;}
    ll ans=dis[n];
    for(rg int j=M;~j;--j)
        if((ans^t[j])>ans)ans^=t[j];
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40515553/article/details/80463029