• [线性基] Luogu P4151 最大XOR和路径


    题目描述

    XOR(异或)是一种二元逻辑运算,其运算结果当且仅当两个输入的布尔值不相等时才为真,否则为假。 XOR 运算的真值表如下(11 表示真, 00 表示假):

    QQ20180128145629.png

    而两个非负整数的 XOR 是指将它们表示成二进制数,再在对应的二进制位进行 XOR 运算。

    譬如 1212 XOR 99 的计算过程如下:

    QQ20180128145728.png

    故 1212 XOR 9 = 59=5。

    容易验证, XOR 运算满足交换律与结合律,故计算若干个数的 XOR 时,不同的计算顺序不会对运算结果造成影响。从而,可以定义 KK 个非负整数 A_1A1A_2A2,……,A_{K-1}AK1A_KAK的 XOR 和为

    A_1A1 XOR A_2A2 XOR …… XOR A_{K-1}AK1 XOR A_KAK

    考虑一个边权为非负整数的无向连通图,节点编号为 11 到 NN,试求出一条从 11 号节点到 NN 号节点的路径,使得路径上经过的边的权值的 XOR 和最大。

    路径可以重复经过某些点或边,当一条边在路径中出现了多次时,其权值在计算 XOR 和时也要被计算相应多的次数,具体见样例。

    输入输出格式

    输入格式:

    输入文件 xor.in 的第一行包含两个整数 NN 和 MM, 表示该无向图中点的数目与边的数目。

    接下来 MM 行描述 MM 条边,每行三个整数 S_iSi, T_iTi , D_iDi, 表示 S_iSi 与 T_iTi 之间存在一条权值为 D_iDi 的无向边。

    图中可能有重边或自环。

    输出格式:

    输出文件 xor.out 仅包含一个整数,表示最大的 XOR 和(十进制结果)。

    输入输出样例

    输入样例#1: 
    5 7
    1 2 2
    1 3 2
    2 4 1
    2 5 1
    4 5 3
    5 3 4
    4 3 2
    输出样例#1: 
    6

    说明

    【样例说明】

    QQ20180128150132.png

    如图,路径1 ightarrow 2 ightarrow 4 ightarrow 3 ightarrow 5 ightarrow 2 ightarrow 4 ightarrow 512435245对应的XOR和为

    22 XOR 11 XOR 22 XOR 44 XOR 11 XOR 11 XOR 3 = 63=6

    当然,一条边数更少的路径1 ightarrow 3 ightarrow 5135对应的XOR和也是22 XOR 4 = 64=6。

    【数据规模】

    对于 20 \%20% 的数据,N leq 100N100, M leq 1000M1000,D_i leq 10^{4}Di104;

    对于 50 \%50% 的数据,N leq 1000N1000, M leq 10000M10000,D_i leq 10^{18}Di1018;

    对于 70 \%70% 的数据,N leq 5000N5000, M leq 50000M50000,D_i leq 10^{18}Di1018;

    对于 100 \%100% 的数据,N leq 50000N50000, M leq 100000M100000,D_i leq 10^{18}Di1018。

    题解

    • 任意一条1到n的路径的异或和,都可以由任意一条1到n路径的异或和与图中的一些环的异或和来组合得到
    • 在这种条件下,我们可以考虑把环储存为一个线性基的元素
    • 如果有多条1到n的路径,那么这显然也构成一个环,也是可以抵消异或的任意一条其他的路径
    • 然后就好做了

    代码

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <cstring>
     4 #define ll long long
     5 using namespace std;
     6 const ll N=110,M=50010;
     7 ll n,m,cnt,vis[M],head[M*2],dis[M],mi[N],b[N];
     8 struct edge{ ll from,to,v; }e[M*4];
     9 void insert(ll x,ll y,ll v)
    10 {
    11     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt,e[cnt].v=v;
    12     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt,e[cnt].v=v;
    13 }
    14 void update(ll x) { for (ll i=60;i>=0;i--) if (mi[i]&x) { if (b[i]) x^=b[i]; else { b[i]=x; break; } } }
    15 void dfs(ll x)
    16 {
    17     vis[x]=1;
    18     for (ll i=head[x];i;i=e[i].from) if (vis[e[i].to]) update(dis[e[i].to]^e[i].v^dis[x]); else dis[e[i].to]=dis[x]^e[i].v,dfs(e[i].to);
    19 }
    20 ll query(ll x)
    21 {
    22     ll ans=x;
    23     for (ll i=60;i>=0;i--) ans=max(ans,ans^b[i]);
    24     return ans;
    25 }
    26 int main()
    27 {
    28     scanf("%lld%lld",&n,&m);
    29     mi[0]=1; for (ll i=1;i<=60;i++) mi[i]=mi[i-1]*2;
    30     for (ll i=1,x,y,z;i<=m;i++) scanf("%lld%lld%lld",&x,&y,&z),insert(x,y,z);
    31     dfs(1),printf("%lld",query(dis[n]));    
    32 } 
  • 相关阅读:
    地址标记,SpringMVC转发与调用相关知识存档
    SpringMVC+MyBatis项目分析与开发实例
    程序开发思路
    web.xml相关知识摘录整理
    Spring AOP
    Spring+Struts2/Hibernate 学习笔记
    Spring学习笔记 Part.01
    用java实现简单TCP服务器监听
    c语言希尔排序,并输出结果(不含插入排序)
    用java实现AVL树并打印结果
  • 原文地址:https://www.cnblogs.com/Comfortable/p/11200199.html
Copyright © 2020-2023  润新知