Wannafly挑战赛1-E.cut(线性基+贡献度)
来源:互联网 发布:java乱码怎么解决 编辑:程序博客网 时间:2024/05/17 03:10
给定一个无向简单图(即无重边无自环). 每条边都有一个权值. 这个图的一个鸽, 指的是将它的点集划分为两个不重不漏的集合S和T. 这个鸽的权值, 是所有两个端点分别属于S和T的边的权值的异或和(即, S内部的边和T内部的边都不算). 现在问这个图的鸽的所有可能权值的和是多少. 由于这个数很大, 只需要输出前9位, 不足9位则全部输出.(
0<n<100001,0<m<200001 )
思路:
有一个骚操作就是。把点v的所有相连的边的边权异或起来,作为点权。
那么如果两个相邻点异或一下,则这条边就不被计入了,等价于这条边不在割内。那么任取若干个点权异或,其结果就代表着一种划分方案。
也就是现在问你n个点,可以产生的不同的异或和的加和是多少。那么可以考虑求出线性基。如果有r个线性基,再考虑到每位的贡献度,如果这一位为1,它对最终的答案的贡献度为
#include <bits/stdc++.h>using namespace std;const int maxn = 100001 + 5;int v[maxn], pos[50];int main(){ int vs, es; scanf("%d%d", &vs, &es); for(int i = 0; i < es; ++i) { int x, y, w; scanf("%d%d%d", &x, &y, &w); v[x] ^= w, v[y] ^= w; } //构造线性基 for(int i = 1; i <= vs; ++i) { for(int j = 30; j >= 0; --j) { if(v[i] & (1 << j)) { if(pos[j]) v[i] ^= pos[j]; else { pos[j] = v[i]; break; } } } } int r = 0; for(int i = 0; i <= 30; ++i) if(pos[i]) ++r; long long ans = 0; for(int i = 0; i <= 30; ++i) { for(int j = 0; j <= 30; ++j) { if(pos[j] & (1 << i)) { ans += (1 << i); break; } } } ans = ans << (r - 1); while(ans >= 1000000000) ans /= 10; printf("%lld\n", ans); return 0;}
阅读全文
0 0
- Wannafly挑战赛1-E.cut(线性基+贡献度)
- nowcode Cut(Wannafly挑战赛1 E)
- Wannafly挑战赛6-E:双拆分数(思维)
- Wannafly挑战赛1 A.Treepath(dfs)
- Wannafly挑战赛1A-(树形DP)
- Wannafly挑战赛1B-(二分)
- Wannafly挑战赛1-C.MMset2(LCA)
- Wannafly挑战赛1 Treepath
- NowCoder Wannafly 挑战赛1
- Wannafly挑战赛1_MMSet2
- Wannafly挑战赛1 B
- Wannafly挑战赛1 C
- Wannafly挑战赛4 E 二次剩余
- 【Wannafly挑战赛6】 A B C E
- Wannafly挑战赛1 A.Treepath
- Wannafly挑战赛1 A Treepath
- Wannafly挑战赛1 B Xorto
- Wannafly挑战赛1 CMMSet2(lca)
- 实验9 MapReduce-分布式缓存
- 徐登沿的第四个程序(如何输出a,b,c三个变量的值)
- 关于logback的基础配置
- kafka数据保存时间问题与kafka的性能测试
- Cube
- Wannafly挑战赛1-E.cut(线性基+贡献度)
- 021 矩阵相似性质
- img图片居中和div居中遇到的坑
- 不同数字的特殊字符
- 6.7产值翻倍
- HDU-1003 Max Sum (线性dp 最大连续和)
- VS2012(InstallShield2015LimitedEdition)打包程序详解
- 车牌识别SDK支持Android、ios
- Python(可重入锁-线程同步之条件变量-队列-线程通信event-线程合并join-多进程)