[WC2011]最大XOR和路径(贪心+线性基)

题目大意:给一张无向图,求一条1-n的路径,是路径边权的异或和最小。

题解

这道题的思路很妙,首先我们可以随便找出一条从1到n的路径来,然后我们可以选一些环。

其实不管这个环和这条路径有怎样的关系,我们都是可以直接选的。

比如说选了一个和这个路径没有交的环,等价于从1走到了这个环然后走了一圈又走回到了1,一条边被异或两次相当于吗,没走。

对于和路径有交的环,异或上它相当于把有交的部分异或两次,相当于走了这个环,也是合法的。

然后我们把所有环插入线性基中,预处理可以用dfs实现。

代码

#include<iostream>
#include<cstdio>
#define N 100002
using namespace std;
typedef long long ll;
ll dis[N],tot,head[N],b[100],n,m;
bool vis[N];
inline ll rd(){
    ll x=0;char c=getchar();bool f=0;
    while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return f?-x:x;
}
struct edge{int n,to;ll l;}e[N<<1];
inline void add(int u,int v,ll l){e[++tot].n=head[u];e[tot].to=v;e[tot].l=l;head[u]=tot;}
inline void ins(ll x){
    for(int i=62;i>=0;--i)if((1ll<<i)&x){
        if(b[i])x^=b[i];
        else{b[i]=x;return;}
    }
}
inline ll query(ll x){
    for(int i=62;i>=0;--i)if((b[i]^x)>x)x^=b[i];
    return x;
}
void dfs(int u){
    vis[u]=1;
    for(int i=head[u];i;i=e[i].n){
        int v=e[i].to;
        if(vis[v])ins(dis[u]^dis[v]^e[i].l);
        else dis[v]=dis[u]^e[i].l,dfs(v);
    }
}
int main(){
    n=rd();m=rd();ll u,v,w;
    for(int i=1;i<=m;++i){
        u=rd();v=rd();w=rd();
        add(u,v,w);add(v,u,w);
    }
    dfs(1);
    printf("%lld\n",query(dis[n]));
    return 0;
}

 

posted @ 2018-12-22 11:32  comld  阅读(167)  评论(0编辑  收藏  举报