「WC2011」最大XOR和路径 题解

题目链接

 

思路

   首先看到题面,“最大”“异或”,联想到了什么?

   没错,线性基。

   不会的同学请先学习:线性基

   但是这道题,因为是在图里,所以不能直接简单地用线性基求解。

 

   观察题目中的图,我们可以发现(吗?),答案一定是由从 $1$ 到 $N$ 的一条路径上的异或和以及若干环上的异或和构成的。

   首先我们要理清一个问题:从 $1$ 到 $N$ 的路径不用特意去选,它对答案没有任何影响。

   借用大佬的博客 来解释:称从 $1$ 到 $N$ 的路径为“主要路”。
   可以发现,所有的“主要路”两两之间会构成一个环。

   如果一条“主要路” $A$ 优于 $B$,而我们选择了 $B$。

   但 $A$ 和 $B$ 也会构成一条环加入线性基,如果更优,肯定会在求解环节被异或上。

   这样一来,就相当于沿 $A$ 跑了一遍。

   回到原来的问题,那么我们要选择哪些环使得异或和最大呢?

   这个时候,我们就会发现,又绕回了最基本的最大异或和问题。

   那么我们就可以把路径上的每个环上的异或和放入线性基,最后用我们“主要路”的路径和为基数,去求解最大异或和。

   就是这样啦(*^▽^*)

   那么,上代码!

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 50005;
const int maxm = 100005;
typedef unsigned long long ull;
struct edge {
    int to,next;
    ull dis;
    edge() {
        to = next = dis = 0;
    }
    edge(int to,int next,ull dis):to(to),next(next),dis(dis){}
}Edge[maxm << 1];
int head[maxn],cnt;
void add(int u,int v,ull t) {
    Edge[++ cnt] = edge(v , head[u] , t);
    head[u] = cnt;
    return ;
}
ull d[70];
void insert(ull x) {
    for(int i = 63;i >= 0;-- i) {
        if((x >> i) & 1) {
            if(d[i])x ^= d[i];
            else {  
                d[i] = x;
                break ;
            }
        }
    }
    return ;
}
int n,m;
ull sum[maxn];
bool vis[maxn];
void dfs(int x,ull ans) {
    vis[x] = true;
    sum[x] = ans;
    for(int i = head[x];i;i = Edge[i].next) {
        int v = Edge[i].to;
        ull w = Edge[i].dis;
        if(!vis[v]) {
            dfs(v , ans ^ w);
        }
        else {//
            insert(ans ^ w ^ sum[v]);//这里是环上的异或和
            //画个图,思考一下,为什么环上异或和是这样 
        }
    }
    return ;                   
}
ull query(ull x) {
    for(int i = 63;i >= 0;-- i) {
        if((x ^ d[i]) > x)x ^= d[i];
    }
    return x;
}
int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= m;++ i) {
        int u,v;
        ull t;
        scanf("%d%d%llu",&u,&v,&t);
        add(u , v , t);
        add(v , u , t);
    }                         
    dfs(1 , 0);
    printf("%llu",query(sum[n]));
    return 0;
}
View Code

 完结撒花✿✿ヽ(°▽°)ノ✿

posted @ 2021-02-11 11:38  ImALAS  阅读(81)  评论(0)    收藏  举报