Description

给定一个无向连通图,边有边权,求一个 \(1~\sim n\) 的路径,最大化边权的异或和。如果一条边经过多次则计算多次。

Input

第一行是两个整数 \(n,m\) 代表点数和边数

下面 \(m\) 行每行三个整数描述一条边

Output

输出一行一个整数代表答案

Hint

\(1~\leq~n~\leq~50000,1~\leq~m~\leq~100000,1~\leq~\) 边权 \(\leq~10^{18}\)

Solution

首先注意到一个结论:对于所有的简单环,环上边权的异或和都可以无代价的获取。原因是可以从一号点出发进入该环绕一圈后原路返回。由于一条路径绕两边对答案的贡献为 \(0\) ,所以这些简单环的异或和都可以无代价取得。那么现在问题就转化成了寻找一条 \(1\) 到 \(n\) 的路径,再异或上一些简单环的异或和,最大化答案。

我们考虑应该寻找哪一条路径:事实上任选一条路径即可。原因是选择的路径和答案路径一定可以构成一个环,所以异或上该环的权值就可以得到最优解。

考虑最大化异或和可以使用线性基解决。时间复杂度 \(O(m~+~n~\log^2d)\),其中 \(d\) 为边权

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#define printtime()
#else
#include <ctime>
#define printtime() printf("Times used = %ld ms\n", clock())
#endif
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
int top=0;
do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 50010;
const int maxm = 200010;
const int maxl = 61; struct Edge {
int to;
ll v;
Edge *nxt;
};
Edge edge[maxm], *hd[maxn]; int ecnt;
inline void cont(ci from, ci to, cl v) {
Edge &e = edge[++ecnt];
e.to = to; e.nxt = hd[from]; e.v = v; hd[from] = &e;
} int n, m;
ll ans;
bool vis[maxn];
ll val[maxn], lb[maxl]; void reading();
void insert(ll);
void dfs(ci, cl); int main() {
freopen("1.in", "r", stdin);
qr(n); qr(m);
reading();
dfs(1, 0);
for (int i = maxl - 1; ~i; --i) {
ans = std::max(ans, ans ^ lb[i]);
}
qw(ans, '\n', true);
printtime();
return 0;
} void reading() {
int a, b; ll c;
for (int i = 1; i <= m; ++i) {
a = 0; b = 0; c = 0; qr(a); qr(b); qr(c);
cont(a, b, c); cont(b, a, c);
}
} void dfs(ci u, cl tp) {
vis[u] = true; val[u] = tp;
if (u == n) ans = tp;
for (Edge *e = hd[u]; e; e = e->nxt) {
int to = e->to;
if (!vis[to]) dfs(to, tp ^ e->v);
else insert(tp ^ e->v ^ val[to]);
}
} void insert(ll x) {
for (int i = maxl - 1; ~i; --i) if (x & (1ll << i)) {
if (lb[i]) {
x ^= lb[i];
} else {
lb[i] = x;
for (int j = maxl - 1; j > i; --j) if (lb[j]) {
lb[j] ^= x;
}
for (int j = 0; j < i; ++j) if (lb[j] & (1ll << i)) {
lb[i] ^= lb[j];
}
break;
}
}
}

【线性基/神仙题】P4151 [WC2011]最大XOR和路径的更多相关文章

  1. 洛谷 P4151 [WC2011]最大XOR和路径 解题报告

    P4151 [WC2011]最大XOR和路径 题意 求无向带权图的最大异或路径 范围 思路还是很厉害的,上午想了好一会儿都不知道怎么做 先随便求出一颗生成树,然后每条返祖边都可以出现一个环,从的路径上 ...

  2. P4151 [WC2011]最大XOR和路径

    P4151 [WC2011]最大XOR和路径 一道妙极了的题. 首先直接从1走到n 然后现在图上有很多环 所以可以在走到n之后走到环上一个点,再走一遍环,再原路返回.这样就会xor上环的权值. 然后只 ...

  3. 洛谷P4151 [WC2011] 最大XOR和路径 [线性基,DFS]

    题目传送门 最大XOR和路径 格式难调,题面就不放了. 分析: 一道需要深刻理解线性基的题目. 好久没打过线性基的题了,一开始看到这题还是有点蒙逼的,想了几种方法全被否定了.还是看了大佬的题解才会做的 ...

  4. 洛谷P4151 [WC2011]最大XOR和路径(线性基)

    传送门 不知道线性基是什么东西的可以看看蒟蒻的总结 首先看到异或就想到线性基 我们考虑有一条路径,那么从这条路径走到图中的任意一个环再走回这条路径上,对答案的贡献是这个环的异或和,走到这个环上的路径对 ...

  5. [洛谷P4151][WC2011]最大XOR和路径

    题目大意:给你一张$n$个点$m$条边的无向图,求一条$1->n$的路径,使得经过路径值的异或值最大(重复经过重复计算) 题解:某条路$k$被重复走了两次,那么它的权值对答案的贡献就是$0$,但 ...

  6. P4151 [WC2011]最大XOR和路径 线性基

    题目传送门 题意:给出一幅无向图,求1到n的所有路径中最大异或和,一条边可以被重复经过. 思路: 参考了大佬的博客 #pragma GCC optimize (2) #pragma G++ optim ...

  7. [WC2011]最大XOR和路径(线性基)

    P4151 [WC2011]最大XOR和路径 题目描述 XOR(异或)是一种二元逻辑运算,其运算结果当且仅当两个输入的布尔值不相等时才为真,否则为假. XOR 运算的真值表如下( 1 表示真, 0 表 ...

  8. [WC2011]最大XOR和路径 线性基

    [WC2011]最大XOR和路径 LG传送门 需要充分发掘经过路径的性质:首先注意不一定是简单路径,但由于统计的是异或值,重复走是不会被统计到的,考虑对于任意一条从\(1\)到\(n\)的路径的有效部 ...

  9. 题解-[WC2011]最大XOR和路径

    [WC2011]最大XOR和路径 给一个 \(n\) 个点 \(m\) 条边(权值为 \(d_i\))的无向有权图,可能有重边和子环.可以多次经过一条边,求 \(1\to n\) 的路径的最大边权异或 ...

随机推荐

  1. Linux 文件搜索命令:find、which、whereis 和 locate

    Linux 提供了许多用于文件搜索的命令,这些命令都很强大,但是也有一些不同之处,这里分别介绍一下. 一.find 命令 find 是最常见和最强大的一个文件搜索命令.使用 find 命令可以在指定目 ...

  2. 机器学习之k-最近邻(kNN)算法

    一.kNN(k-nearest neighbor)算法原理 事物都遵循物以类聚的思想,即有相同特性的事物在特征空间分布上会靠得更近,所以kNN的思路是:一个样本在特征空间中k个靠的最近的样本中,大多数 ...

  3. Python入门学习系列——Python文件和异常

    从文件中读取数据 首先准备一个文本文件,文件中存储着普通文本数据.读取文件需要调用open()和read()函数. 读取整个文件 代码示例: with open('pi_digits.txt') as ...

  4. Python3入门机器学习 - k近邻算法

    邻近算法,或者说K最近邻(kNN,k-NearestNeighbor)分类算法是数据挖掘分类技术中最简单的方法之一.所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代 ...

  5. linux 常用命令-配置登陆方式

    使用阿里云服务器,启动实例(ubuntu 7.4,密码登录)后,通过xshell登陆,但是发现xshell中密码登录是灰色禁用的,很惆怅啊,明明设置的就是密码登录,在xshell中找了一通设置发现并没 ...

  6. Java每日编程day2

    Java每日编程day2 第一题 package com.pcx.day2; /* * 九九乘法表并逆序 */ public class JiuJiu { public static void mai ...

  7. struts2.3.16.1+hibernate4.3.4+spring4.0.2

    把之前的老项目用新的改了 发现新的有点很方便啊 Struts2+Hibernate+Spring整合     用的是      struts2.3.16.1      hibernate4.3.4   ...

  8. Journal entry of the thirteenth chapter to chapter seventeenth(第十三章和十七章阅读与疑问)

    第十三章: 软件测试的意义在于: a.     发现软件错误: b.     有效定义和实现软件成分由低层到高层的组装过程: c.     验证软件是否满足任务书和系统定义文档所规定的技术要求: d. ...

  9. What is ASP.NET SignalR

    什么是ASP.NET SignalR ASP.NET SignalR是ASP.NET开发人员的新库,它使得为应用程序添加实时Web功能变得非常简单. 什么是“实时网络”功能?它能够让您的服务器端代码实 ...

  10. Java中实现PCA降维

    package com.excellence.splitsentence; import java.net.UnknownHostException; import java.util.ArrayLi ...