www.lydsy.com/JudgeOnline/problem.php?id=2115 (题目链接)

题意

  给出一张图,可能有重边和自环,在图中找出一条从1~n的路径,使得经过的路径的权值的异或和最大,每条边可以重复经过并且重复计算异或和。

Solution

  刚看到这道题,想了10分钟完全没有思路,于是就膜了题解。

  我们先把图看成一棵树,那么我们所需要找出的路径可以分成一些环和一条从1~n的树上路径,至于树是怎么构造的以及那条从1~n的路径是怎么走的并不重要,因为我们可以通过在总路径上补环来增大异或和。于是这个问题就转化为了如何在环的异或和中选出一些使得这些值异或上从1~n的路径的异或和最大。

  于是我们先dfs一遍把环以及它的异或和抠出来,当然这些环可能并不完全,但它们可以通过互相异或来异或出没有得到的环。如果发现当前节点x的目标节点e[i].to已经被走过了,那么这个环的异或和就是${dis[x]~XOR~dis[e[i].to]~XOR~e[i].w}$。

  怎么求最大异或和呢?这需要用到一个很神的东西:线性基

  什么是线性基:

  若干数的线性基是一组数a1,a2,…an,其中ax的最高位的1在第x位。通过线性基中元素xor出的数的值域与原来的数xor出数的值域相同。 
  线性基主要有2个优秀的性质: 
  可以O(k)(二进制的位数)的求出能异或出的最大值,或者是判断一个数能否被异或出来。

  线性基的构造:

  线性基的构造有两种: 
  第一是高斯消元。通过高斯消元将二进制矩阵消成上三角矩阵或者是对角矩阵,当然消成后者时间复杂度略高,但也更为方便,求解异或和最大时一路for下去就可以了。而上三角矩阵需要判断如果答案异或上这个值能否使答案增大。 
  第二种就是一种拟阵贪心,详情参见jump大爷的博客——www.cnblogs.com/ljh2000-jump/p/5869991.html,因为证明太高深,这里也就不再赘述。

  所以这道题就很好做了对吧,这里我选择消成对角矩阵,性质就更加显然一些。

代码

// bzoj2115
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi 3.1415926535898
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=50010,maxm=100010;
struct edge {int to,next;LL w;}e[maxm<<1];
LL dis[maxn],c[maxm<<2],bin[65];
int vis[maxn],n,m,tot,sum,cnt,head[maxn]; void link(int u,int v,LL w) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void dfs(int x) {
vis[x]=1;
for (int i=head[x];i;i=e[i].next) {
if (!vis[e[i].to]) {
dis[e[i].to]=dis[x]^e[i].w;
dfs(e[i].to);
}
else c[++sum]=dis[x]^dis[e[i].to]^e[i].w;
}
}
void Gauss() {
for (LL i=bin[60];i;i>>=1) {
int j=tot+1;
while (j<=sum && !(c[j]&i)) j++;
if (j==sum+1) continue;
swap(c[++tot],c[j]);
for (j=1;j<=sum;j++) if (j!=tot && c[j]&i) c[j]^=c[tot];
//for (int k=j+1;k<=sum;k++) if (c[k]&i) c[k]^=c[tot];
}
}
int main() {
bin[0]=1;for (int i=1;i<=60;i++) bin[i]=bin[i-1]<<1;
scanf("%d%d",&n,&m);
for (int u,v,i=1;i<=m;i++) {
LL w;
scanf("%d%d%lld",&u,&v,&w);
link(u,v,w);
}
dfs(1);
Gauss();
LL ans=dis[n];
for (int i=1;i<=tot;i++) ans=max(ans,ans^c[i]);
printf("%lld\n",ans);
return 0;
}

  

【bzoj2115】 Xor的更多相关文章

  1. 【BZOJ2115】Xor(线性基)

    [BZOJ2115]Xor(线性基) 题面 BZOJ Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si ...

  2. 【BZOJ-2115】Xor 线性基 + DFS

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2142  Solved: 893[Submit][Status] ...

  3. 【BZOJ2115】[Wc2011] Xor 高斯消元求线性基+DFS

    [BZOJ2115][Wc2011] Xor Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ...

  4. 【BZOJ2337】Xor和路径(高斯消元)

    [BZOJ2337]Xor和路径(高斯消元) 题面 BZOJ 题解 我应该多学点套路: 对于xor之类的位运算,要想到每一位拆开算贡献 所以,对于每一位拆开来看 好了,既然是按位来算 我们就只需要计算 ...

  5. 【bzoj2115】[Wc2011] Xor

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2512  Solved: 1049[Submit][Status ...

  6. 【HDU3949】XOR

    [题目大意] 给定一个数组,求这些数组通过异或能得到的数中的第k小是多少. 传送门:http://vjudge.net/problem/HDU-3949 [题解] 首先高斯消元求出线性基,然后将k按照 ...

  7. 【bzoj2115】【wc2011】Xor

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 5380  Solved: 2249[Submit][Status ...

  8. bzoj2115【WC2001】Xor

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 2059  Solved: 856 [Submit][Statu ...

  9. 【bzoj2115】[Wc2011] Xor DFS树+高斯消元求线性基

    题目描述 输入 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边. 图 ...

随机推荐

  1. [转]在Eclipse中使用JUnit4进行单元测试(高级篇)

    通过前2篇文章,您一定对JUnit有了一个基本的了解,下面我们来探讨一下JUnit4中一些高级特性. 一.高级Fixture 上一篇文章中我们介绍了两个Fixture标注,分别是@Before和@Af ...

  2. 查​看​和​设​置​o​r​a​c​l​e​数​据​库​的​最​大​连​接​数

    当前的连接数 select count(*) from v$process; 设置的最大连接数(默认值为150) select value from v$parameter where name = ...

  3. swift 判断输入的字符串是否为数字

    // 判断输入的字符串是否为数字,不含其它字符 func isPurnInt(string: String) -> Bool { let scan: Scanner = Scanner(stri ...

  4. SSH公钥认证+优化

    一 ssh公钥认证流程: sshclinet机器:产生公私钥(公钥相当于一把锁) sshclient:将公钥发给sshserver(抛出锁子) sshclinet去连sshserver不需要密钥   ...

  5. Linux Linux程序练习五

    题目:编写两个进程a和b,利用共享内存技术,a向共享内存写字符串,b将从共享内存中读到的字符串在屏幕上打印出来. //创建共享内存区 #include <stdio.h> #include ...

  6. ZooKeeper学习第八期——ZooKeeper伸缩性

    一.ZooKeeper中Observer 1.1 ZooKeeper角色 经过前面的介绍,我想大家都已经知道了在ZooKeeper集群当中有两种角色Leader和Follower.Leader可以接受 ...

  7. [CareerCup] 1.7 Set Matrix Zeroes 矩阵赋零

    1.7 Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column are ...

  8. 如何下载struts 2及其各个包的作用

    一.http://archive.apache.org/dist/struts/library/ 二. struts官网: http://struts.apache.org/ 进入主页后点击" ...

  9. iOS开发--应用设置及用户默认设置——转载

    [链接]iOS开发--应用设置及用户默认设置[1.bundlehttp://www.jianshu.com/p/6f2913f6b218 在iphone里面,应用都会在“设置”里面有个专属的应用设置, ...

  10. Javascript设计模式之我见:迭代器模式

    大家好!本文介绍迭代器模式及其在Javascript中的应用. 模式介绍 定义 提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示. 类图及说明 Iterator抽象迭代器 抽象迭代器负 ...