首页 > 其他分享 >异或最长路(线性基应用)

异或最长路(线性基应用)

时间:2024-11-27 09:55:41浏览次数:5  
标签:int LL dfs 异或 线性 最长 dis

首先异或最长路不能用 Bellman-Ford,因为异或不满足加法传递性,局部最优可能推不出整体最优,而且可能出现类似“负环”的情况,走不出来。一般要用线性基解决这一类问题。

我们可以把路径拆成一条链(蓝色)和若干个环(灰色)。我们可以走一条红色的路径到达一个环,转一圈然后原路返回,这样红色的边两次异或消掉了,我们白白获得了整个环的异或和。因为是连通图,我们可以用这样的方法获得图上所有的环的异或和,把这些异或和扔进一个集合,做子集异或和最大值,转化成了线性基的板子。

image

那么这个链要怎么取呢?发现我们可以随便取,因为如果有一条比这个蓝色链更好的绿色链,蓝色链和绿色链就构成了一个环。在做线性基的过程中,这个环被选入,就相当于把蓝色链异或两次消掉,留下了绿色链。这个过程是自动的,所以不需要单独考虑怎么取链。在 dfs 找环的时候会记录一个从 1 开始的路径异或和,直接使用就好了(见代码,P4151 [WC2011] 最大XOR和路径)。

#include <bits/stdc++.h>
using namespace std;
using LL = long long;

constexpr int N = 50000 + 10;
constexpr int M = 100000 + 10;

int n, m;
LL dis[N], p[61];
bool vis[N];
vector<pair<int, LL>> G[N];

void insert(LL x) { // 贪心法求线性基板子
    for (int i = 60; ~i; i--) {
        if (!(x >> i)) continue;
        if (!p[i]) {
            p[i] = x;
            break;
        }
        x ^= p[i];
    }
}

void dfs(int u, LL d) {
    dis[u] = d; // 记录一个从1开始的异或和
    vis[u] = 1;
    for (auto [v, w] : G[u]) {
        if (vis[v]) { // 找到环了
            insert(dis[u] ^ w ^ dis[v]); // 环的异或和=[1~u]^w^[1~v],环外的部分异或没了
            continue;
        }
        dfs(v, dis[u] ^ w);
    }
}

int main() {
    cin.tie(0)->ios::sync_with_stdio(0);
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        int u, v;
        LL w;
        cin >> u >> v >> w;
        G[u].emplace_back(v, w);
        G[v].emplace_back(u, w);
    }
    dfs(1, 0);
    LL ans = dis[n]; // 直接用dfs出的[1~n]的异或和作为链长
    for (int i = 60; ~i; i--) {
        ans = max(ans, ans ^ p[i]);
    }
    cout << ans << '\n';
    return 0;
}

标签:int,LL,dfs,异或,线性,最长,dis
From: https://www.cnblogs.com/th19/p/18571638

相关文章

  • 蓝桥杯c++算法秒杀【6】之动态规划【下】(数字三角形、砝码称重(背包问题)、括号序列、
    别忘了请点个赞+收藏+关注支持一下博主喵!!!! ! ! ! !关注博主,更多蓝桥杯nice题目静待更新:)动态规划三、括号序列【问题描述】        给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合法,当添加完成后,会产生不同的添加结果,请问有多少种本质......
  • 【贪心算法第五弹——300.最长递增子序列】
    目录1.题目解析题目来源测试用例2.算法原理3.实战代码代码解析注意本题还有一种动态规划的解决方法,贪心的方法就是从动态规划的方法总结而来,各位可以移步博主的另一篇博客先了解一下:动态规划-子序列问题——300.长递增子序列 1.题目解析题目来源300.最长递增......
  • 最长回文字串习题分析
    习题:(leetcode5)给你一个字符串 s,找到 s 中最长的 回文子串。回文字串:子字符串 是字符串中连续的 非空 字符序列。分析:可以先创建一个回文判断函数(isPalindrome),对于一个回文字串将第一个元素和最后一个元素删去后剩余的字串仍是回文字串。使用双重循环进行遍历,找到......
  • 线性空间
    矩阵论学习线性空间是什么?假设V是一个非空集合,P是一个数域。对于任意x、y、z∈V,如果V满足以下条件:在V中定义一个封闭的加法运算:x+y=y+x(x+y)+z=x+(y+z)存在0元素,+0=x存在负元素,x+(-x)=0也就是交换律和结合律,有加法单位元在V中定义一个封闭的数乘运算,即......
  • 机器学习:线性回归(下)
    简介在上一篇文章《机器学习:线性回归(上)》中讨论了二维数据下的线性回归及求解方法,本节中我们将进一步的将其推广至高维情形。章节安排背景介绍最小二乘法梯度下降法程序实现一、背景介绍1.1超平面\(L\)的定义定义在\(D\)维空间中的超平面\(L\)的方程为:\[\begin{alig......
  • LeetCode题练习与总结:数组中两个数的最大异或值--421
    一、题目描述给你一个整数数组 nums ,返回 nums[i]XORnums[j] 的最大运算结果,其中 0≤i≤j<n 。示例1:输入:nums=[3,10,5,25,2,8]输出:28解释:最大运算结果是5XOR25=28.示例2:输入:nums=[14,70,53,83,49,91,36,80,92,51,66,70]输出:127提示:1<=......
  • 【异或运算】codeforces 1153 B. Dima and a Bad XOR
    前言异或运算:是一种在二进制数系统中使用的逻辑运算。它的基本规则是对两个二进制位进行比较,如果这两个位不同,则结果为\(1\);如果相同,则结果为\(0\)。异或运算的规则\(0\)XOR\(0\)=\(0\)\(0\)XOR\(1\)=\(1\)\(1\)XOR\(0\)=\(1\)\(1\)XOR\(1\)=\(0\)特性......
  • 线性代数
    Chapter1IntroductiontoVectors1.1向量定义1.1.1向量中学阶段只讨论向量的几何意义,由此我们只能想象出二维和三维的向量。从代数角度,我们可以定义\(n\)维的向量。定义笛卡尔积为两个集合的运算\(A\timesB=\{(u,v)\midu\inA,v\inB\}\),其元素是二元组\((u,v)\)。......
  • KMP与Lca应用——最长公共border
    问题提出给定你一个字符串,有\(n\)次询问,每次给出两个数\(a\),\(b\),希望求出该字符串以\(a\),\(b\)下标结尾的两段前缀的最长公共\(border\)。(一个字符串的\(border\)同时为其后缀与前缀)初步分析首先我们需要考虑一个字符串的最长\(border\)求法,毕竟需要求的是两字符串的最长公......
  • 最长公共子序列
    前言顾名思义:a,b串删去一些字符后得到的相同字串模板#include<bits/stdc++.h>usingnamespacestd;#defineN1000005intn,m;chara[N];charb[N];intdp[1000][10000];intx[N],y[N];intmain(){cin>>n>>m;for(inti=1;i<=n;i++){cin&g......