HDU 5544 Ba Gua Zhen ( 2015 CCPC 南阳 C、DFS+时间戳搜独立回路、线性基 )
题目链接
题意 : 给出一副简单图、要你找出一个回路、使得其路径上边权的异或和最大
分析 :
类似的题有 BZOJ 2115
对于这种异或最长路的题目(走过的边可以重复走)
答案必定是由一条简单路径(链) + 一些基本环构成
这是因为操作是 xor , 具有自反性质 , 可能需要脑补一下
回到这题, 发现答案就是要求找出一个环
那么根据上面那道题目的启发
答案是一个环的情况下, 那么答案环必定也是由其他环来组成
那么只要找出图中所有的基本环, 就可以由这些基本环来线性组合出最大 xor 环了
有一个定理
对于一个图而言、其独立回路的个数为 M - N + 1
独立回路是指任意一个都不能由其他回路构成。
引用一段数学归纳法证明:
“M=N-1时,树,结论成立
设M=K时结论成立,当M=K+1时,任取G中一条边e,G-e中有K-N+1个独立回路,且
任取一个包含e的回路C,显然独立于之前的回路
任意两个包含e的回路C1与C2,C12=C1+C2是G-e的回路,C2不独立
故能且仅能增加一个包含e的独立回路
从而G中恰有(K+1)-N+1个独立回路,证毕”
红色字体引用自 ==> Click here
即一个图最多只有 M + ( N - 1 ) 个独立回路 (即基本环)
而除开独立回路外的图中剩余所有回路都能被这 M - N + 1 个独立回路线性表示
那么由于异或拥有自反性质、即走过两遍的路径不会产生贡献
接下来如果能找出所有的独立回路、这样问题就变成了、给出 N 个数
从中找出异或和最大的组合、这个可以用线性基轻松做到
如何用DFS找出图中所有的独立回路?
首先你考虑生成树, 对于一个图的生成树而言
其基本环(不能由其他环线性表示的环)就是任意两个树上节点 + 非树边构成
那么先 DFS 出生成树, 加上时间戳, 若干当前节点的时间戳大于被遍历到的节点的时间戳
则说明找到一个上面那样子的非树边, 即找到了一个基本环
这样子找出来的环正好有 M - ( N - 1 ) 即所有的边 - 树边这么多
参考自 ==> Click here , Click here
#include<bits/stdc++.h> #define LL long long #define ULL unsigned long long#define scl(i) scanf("%lld", &i) #define scll(i, j) scanf("%lld %lld", &i, &j) #define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k) #define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)#define scs(i) scanf("%s", i) #define sci(i) scanf("%d", &i) #define scd(i) scanf("%lf", &i) #define scIl(i) scanf("%I64d", &i) #define scii(i, j) scanf("%d %d", &i, &j) #define scdd(i, j) scanf("%lf %lf", &i, &j) #define scIll(i, j) scanf("%I64d %I64d", &i, &j) #define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k) #define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k) #define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k) #define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l) #define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l) #define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)#define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define lowbit(i) (i & (-i)) #define mem(i, j) memset(i, j, sizeof(i))#define fir first #define sec second #define VI vector<int> #define ins(i) insert(i) #define pb(i) push_back(i) #define pii pair<int, int> #define VL vector<long long> #define mk(i, j) make_pair(i, j) #define all(i) i.begin(), i.end() #define pll pair<long long, long long>#define _TIME 0 #define _INPUT 0 #define _OUTPUT 0 clock_t START, END; void __stTIME(); void __enTIME(); void __IOPUT(); using namespace std;const int maxn = 5e4 + 10;struct EDGE{ int v, nxt; LL w; }Edge[maxn<<2];int Head[maxn], EdgeCnt = 0;int n, m;inline void EdgeInit() {mem(Head, -1);EdgeCnt = 0; }inline void AddEdge(int from, int to, LL weight) {int & cnt = EdgeCnt;Edge[cnt].v = to;Edge[cnt].w = weight;Edge[cnt].nxt = Head[from];Head[from] = cnt++; }struct L_B {LL d[65], p[65];int cnt;void init() {memset(d, 0, sizeof(d));memset(p, 0, sizeof(p));cnt = 0;} // 1e18以内的数都适用.bool Insert(LL val) {for (int i = 63 ; i >= 0 ; i --) {if (val & (1ll << i)) {if (!d[i]) {d[i]=val;break;}val^=d[i];}}return val > 0;// 可判断val是否存在于线性基当中. }LL query_max() {LL res = 0;for (int i = 63 ; i >= 0 ; i --) {if ((res^d[i]) > res) res ^= d[i];}return res;}LL query_min() { // 应该预先判断能否是0的情况..QAQfor (int i = 0 ; i <= 60 ; i ++) {if (d[i]) return d[i];}return 0;}void rebuild() { // 用于求第k小值.需要先进行独立预处理for (int i = 60 ; i >= 0 ; i --) {for (int j = i-1 ; j >= 0 ; j --) {if (d[i] & (1ll<<j)) d[i] ^= d[j];}}for (int i = 0 ; i <= 60 ; i ++) {if (d[i]) p[cnt++]=d[i];}}LL kthquery(LL k) { // 注意判断原序列异或出0的情况, 此时应该将k -- 在进行后面的操作.LL res = 0;if (k >= (1ll << cnt)) return -1;for (int i = 60 ; i >= 0 ; i --) {if (k & (1LL<<i)) res ^= p[i];}return res;}void Merge(const L_B &b) { // 把b这个线性基插入到当前这个线性基中.for (int i = 60 ; i >= 0 ; i --)if (b.d[i]) Insert(b.d[i]);} }LB;int DFN[maxn]; int DFS_Clocks; LL val[maxn]; VL CycleVal;inline void DFS(int u, int fa) {DFN[u] = ++DFS_Clocks;vis[u] = true;for(int i=Head[u]; ~i; i=Edge[i].nxt){int v = Edge[i].v;if(v == fa) continue;if(vis[v] && DFN[v] < DFS_Clocks){///若当前当前点的时间戳大于出度点、则说明找到一条回路CycleVal.pb(val[v] ^ val[u] ^ Edge[i].w);}else if(!vis[v]){val[v] = val[u] ^ Edge[i].w;DFS(v, u);}} }int main(void){__stTIME();__IOPUT();int nCase;sci(nCase);for(int Case=1; Case<=nCase; Case++){scii(n, m);EdgeInit();for(int i=1; i<=m; i++){int u, v;scii(u, v);LL w;scl(w);AddEdge(u, v, w);AddEdge(v, u, w);}CycleVal.clear();for(int i=0; i<=n; i++)vis[i] = false,val[i] = 0LL;DFS_Clocks = 0;for(int i=1; i<=n; i++)if(!vis[i])DFS(i, -1);LB.init();for(int i=0; i<(int)CycleVal.size(); i++)LB.Insert(CycleVal[i]);printf("Case #%d: %lld\n", Case, LB.query_max());}__enTIME();return 0;}void __stTIME() {#if _TIMESTART = clock();#endif }void __enTIME() {#if _TIMEEND = clock();cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;#endif }void __IOPUT() {#if _INPUTfreopen("in.txt", "r", stdin);#endif#if _OUTPUTfreopen("out.txt", "w", stdout);#endif }
View Code
顺带一提, 找出图中所有的简单环, 这个东西是 NP 的, 正是由于 xor
有自反这种美妙的性质, 才能通过基本环+线性基来做这题
求出图中所有环数量的算法, 也是考虑通过生成树的方法 ==> Click here
Codeforces 也有过一道题目, 要求找出环的数量, 标算是状压 ==> Click here
转载于:https://www.cnblogs.com/LiHior/p/9758095.html
HDU 5544 Ba Gua Zhen ( 2015 CCPC 南阳 C、DFS+时间戳搜独立回路、线性基 )相关推荐
- hdu 5544 Ba Gua Zhen
link 因为在沈阳站的比赛中我们没有做出来H题,后来才知道是高斯消元.于是我先来补一下高斯消元的题目.先做了hdu XOR对线性基有了一定的了解,然后来做一下南阳ccpc的Ba Gua Zhen 分 ...
- hdu 5544 Ba Gua Zhen(线性基+dfs)
题意: 一个无向图,每条边有值,找出无向图中所有的环的异或和,问这些值能异或出来的最大值. 解题思路: 去年的做的比赛里的题,今年才补上. 找环用dfs跑一遍图就可以找出来了,然后求最大的异或和,这是 ...
- [HDU] 5544 Ba Gua Zhen
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5544 题目大意:T组数据, 给一个n个点, m条边的无向连通图, 无自环, 无重边, 求最大XOR回 ...
- HDU 5544 Ba Gua Zhen (dfs独立回路异或消元)
这道题和BZOJ 2115 基本一样,容易一点,直接存个代码:这个代码要好看一点(好像并没有什么区别...) #include <bits/stdc++.h> #define LL lon ...
- 2015南阳CCPC E - Ba Gua Zhen 高斯消元 xor最大
Ba Gua Zhen Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description During the Three-Kingdom perio ...
- Ba Gua Zhen
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5544 学习链接:https://www.cnblogs.com/qscqesze/p/4902518. ...
- hdu5544 Ba Gua Zhen(高斯消元)
思路:首先DFS把图上的所有环找出来,然后就是K个数里面任意选数使得异或和最大,高斯消元就好了 异或方程的高斯消元见 点击打开链接 #include<bits/stdc++.h> usin ...
- UESTC OJ1219 Ba Gua Zhen
链接:http://mozhu.today/#/problem/show/1219 题意:给定n个点m条边有边权的无向图,求一个异或值最大的回路. 分析:其实就是将所有环的异或值找出来然后任选一些组成 ...
- HDU 3949 XOR 线性基
http://acm.hdu.edu.cn/showproblem.php?pid=3949 求异或第k小,结论是第k小就是 k二进制的第i位为1就把i位的线性基异或上去. 但是这道题和上一道线性基不 ...
最新文章
- 作为零基础如何自学软件测试?
- 基于visual Studio2013解决面试题之0608找出两个只出现一次的数
- 风格迁移--U-GAT-IT模型(ICLR 2020)
- 从0到1设计一个秒杀系统
- jquery实现图片等比例缩放,解决max-width在ie中不兼容问题
- java 蓝桥杯算法训练 sign函数
- MVC实用架构设计(三)——EF-Code First(4):数据查询
- html音乐播放标签,html5 视频和音乐播放器标签属性
- element ui 弹窗在IE11中关闭时闪现问题修复
- 如何修改计算机mac,超简单的电脑mac地址查看和修改方法
- 交通信号灯的检测与识别
- 做毕业论文时遇见的问题
- $.ajax %5b%5d,数据传回后台数带有%5B%5D的问题
- 《庄子·内篇·逍遥游第一》
- SEO与SEM区别是什么
- [附源码]Python计算机毕业设计电影票购票系统
- 出现“连接到服务器失败。错误: 0x80080005”错误的解决办法
- android imageview 锯齿,[置顶] android 自定义圆角ImageView以及锯齿的处理
- 计算机 我们一起学猫叫歌词,猫叫是什么歌 抖音我们一起学猫叫完整版歌词
- win10键盘全部没反应_win10笔记本键盘全部没反应 win10键盘全部没反应解决方法...
热门文章
- PlantSimulation切换中文的方法
- SQL*Plus 学习笔记——常用编辑命令
- Java日期和时间JDK—API1.6.0(Date类、Calendar类)
- JAVA SE 是什么? 入门级讲解。
- HTML5QQ登录cav demo
- 输入一个华氏温度,要求输出摄氏温度。公式为 c=5(F-32)/9 输出要求有文字说明,取位2小数。...
- 《实战Java高并发程序设计》github笔记和源码
- 智慧大脑的搭建在智慧工地管理系统中有何作用
- tensorflow玻尔兹曼机_受限玻尔兹曼机(Restricted Boltzmann Machine)
- 配置Eureka时Status显示的是电脑名而不是localhost及ipAddr显示为本机ip的问题