codeforces 724G. Xor-matic Number of the Graph

题目链接http://codeforces.com/contest/724/problem/G
题目大意:给出一张n个点m条边的无向图,对于一个三元组(u,v,s),如果1<=u < v<=n,并且存在一条从u到v的路径(可以重复经过点和边)使得路径上的边权异或和为s,那么我们说它是“有趣的”。求所有有趣的三元组中的 s 之和。
数据范围:1 ≤ n ≤ 100 000, 0 ≤ m ≤ 200 000, 0 ≤ 边权 ≤ 10^18

题解:我们假设这是一张连通图,如果不是那么对每个连通块分别求解即可。
考虑两个点 u 和 v ( u < v ),任取从 u 到 v 的两条路径 p0 和 p1(可以经过相同的边但不能完全相同),得到两个三元组 (u,v,s0) 和 (u,v,s1),路径 p0 和 p1 组合就形成了一个环,假设这个环上的边权异或和为s2,则s2=s0 xor s1,即s1=s0 xor s2。由于p0和p1可能有边相同,所以这个环实际上是由若干个不经过重复的边的环组成。所以我们发现,任意一条从u到v的路径都可以表示成s0 xor 若干个环。
假设我们已经知道了一条从u到v的路径,那么是否对于任意一个环,这条路径与它组合后都会是一条合法的u到v的路径呢?答案是肯定的。因为这是一个连通图,我们只要从u走到环上的任意一个点w,绕环一圈然后原路返回u再从u走到v,则从u到w的路径经过两次,不影响异或的和,于是我们得到了一条由原路径加上一个新的环组成的路径。

得出结论:两个点u和v之间的所有路径都可以由它们之间的某条路径异或图中的任意多个环得到。

所以我们可以求出图中的一棵生成树,计算出每个点到根的异或和f[ i ],那么任意两个点u和v之间的一条路径都可以由f[u] xor f[v]得到(因为从根到它们的公共祖先的路径异或了两次)。对于所有不在环上的边(ui,vi,ti),f[ui] xor f[vi] xor ti 即是图中的一个环。这样我们就得到了图中任意两点之间的一条路径和图中所有的环。

现在的问题是如何求出两个点u和v之间的所有不同的异或和。
首先,我们假设一个数列a1,a2,…an中取其中任意个数可以组成的异或和称为这个数列的值域。有以下结论:对于数列中的任意一个数ai,将所有aj(j≠i)的值变成aj xor ai,该数列的值域不变。证明:假设我们取了原数列的k个数s1=ap1 xor ap2 xor … xor apk,那么新数列对应的k个数的异或和s2=s1 xor j个ai,其中 j=k或k-1取决于这k个数中有没有ai。当 j 为偶数时,j 个ai相互抵消,s1=s2;当 j 为奇数时,只要在新数列中把ai再异或一遍,s1=s2 xor ai。

假设图中的环的异或和为数列c,我们需要求出一个数列d,使得它的值域与c相同,并且d中不存在两种不同的取数方案使得这两种方案的异或和相等,即不存在若干个数的异或和为0(据说这玩意叫线性基)。
我们可以用类似高斯消元的方法来求出这个数列。把c中的数看成60位的二进制数,然后从最高位开始,每次找到一个当前位为1的数(之前选过的数不能再选,找不到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值