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; ; ]; ; int n, m; inline void EdgeInit() { mem(Head, -); EdgeCnt = ; } 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[], p[]; int cnt; void init() { memset(d, , sizeof(d)); memset(p, , sizeof(p)); cnt = ; } // 1e18以内的数都适用. bool Insert(LL val) { ; i >= ; i --) { if (val & (1ll << i)) { if (!d[i]) { d[i]=val; break; } val^=d[i]; } } ; // 可判断val是否存在于线性基当中. } LL query_max() { LL res = ; ; i >= ; i --) { if ((res^d[i]) > res) res ^= d[i]; } return res; } LL query_min() { // 应该预先判断能否是0的情况..QAQ ; i <= ; i ++) { if (d[i]) return d[i]; } ; } void rebuild() { // 用于求第k小值.需要先进行独立预处理 ; i >= ; i --) { ; j >= ; j --) { if (d[i] & (1ll<<j)) d[i] ^= d[j]; } } ; i <= ; i ++) { if (d[i]) p[cnt++]=d[i]; } } LL kthquery(LL k) { // 注意判断原序列异或出0的情况, 此时应该将k -- 在进行后面的操作. LL res = ; ; ; i >= ; i --) { if (k & (1LL<<i)) res ^= p[i]; } return res; } void Merge(const L_B &b) { // 把b这个线性基插入到当前这个线性基中. ; i >= ; 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); ; Case<=nCase; Case++){ scii(n, m); EdgeInit(); ; i<=m; i++){ int u, v; scii(u, v); LL w; scl(w); AddEdge(u, v, w); AddEdge(v, u, w); } CycleVal.clear(); ; i<=n; i++) vis[i] = false, val[i] = 0LL; DFS_Clocks = ; ; i<=n; i++) if(!vis[i]) DFS(i, -); LB.init(); ; i<(int)CycleVal.size(); i++) LB.Insert(CycleVal[i]); printf("Case #%d: %lld\n", Case, LB.query_max()); } __enTIME();;} void __stTIME() { #if _TIME START = clock(); #endif } void __enTIME() { #if _TIME END = clock(); cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl; #endif } void __IOPUT() { #if _INPUT freopen("in.txt", "r", stdin); #endif #if _OUTPUT freopen("out.txt", "w", stdout); #endif }
顺带一提, 找出图中所有的简单环, 这个东西是 NP 的, 正是由于 xor
有自反这种美妙的性质, 才能通过基本环+线性基来做这题
求出图中所有环数量的算法, 也是考虑通过生成树的方法 ==> Click here
Codeforces 也有过一道题目, 要求找出环的数量, 标算是状压 ==> Click here
HDU 5544 Ba Gua Zhen ( 2015 CCPC 南阳 C、DFS+时间戳搜独立回路、线性基 )的更多相关文章
- HDU 5544 Ba Gua Zhen dfs+高斯消元
Ba Gua Zhen Problem Description During the Three-Kingdom period, there was a general named Xun Lu wh ...
- The 2015 China Collegiate Programming Contest E. Ba Gua Zhen hdu 5544
Ba Gua Zhen Time Limit: 6000/4000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total ...
- 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. ...
- ACM学习历程—UESTC 1219 Ba Gua Zhen(dfs && 独立回路 && xor高斯消元)
题目链接:http://acm.uestc.edu.cn/#/problem/show/1219 题目大意是给了一张图,然后要求一个点通过路径回到这个点,使得xor和最大. 这是CCPC南阳站的一道题 ...
- hdu 3949 XOR (线性基)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=3949 题意: 给出n个数,从中任意取几个数字异或,求第k小的异或和 思路: 线性基求第k小异或和,因为题 ...
- HDU 4403 A very hard Aoshu problem(dfs爆搜)
http://acm.hdu.edu.cn/showproblem.php?pid=4403 题意: 给出一串数字,在里面添加一个等号和多个+号,使得等式成立,问有多少种不同的式子. 思路: 数据量比 ...
- HDU 3949 XOR 线性基
http://acm.hdu.edu.cn/showproblem.php?pid=3949 求异或第k小,结论是第k小就是 k二进制的第i位为1就把i位的线性基异或上去. 但是这道题和上一道线性基不 ...
- -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】
[把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...
随机推荐
- idea 如何加入插件SonarLint
idea 如何加入插件SonarLint IDEA的插件安装有两种方法:一是在线安装:二是离线安装,即将插件的安装包下载以后从本地安装. 一.在线安装的过程: 1.打开IDEA ...
- Devexpress xaf针对某个用户登录后在面板中设置导航无效的解决方法
Devexpress xaf框架生成的项目默认情况下导航栏是显示在左侧,有时候我们用某个账户登录后,发现导航栏无法显示在左侧,操作十分不方便.我们可以去数据库删除当前登录用户的自定义布局 解决方法如下 ...
- 后端排序,debug模式中map的顺序出错
js中map遍历的顺序是按照插入的顺序来执行的.如果map的来源是字符串转换的,那么就会按照字符串中key值的顺序进行遍历.千万不要被debug中显示的顺序误导,这里应该是为了方便查看对key进行了字 ...
- Sql Server 分区演练
USE [master] GO if exists (select * from sys.databases where name = 'Test_1') drop database Test_1 G ...
- 如何远程调试部署在CloudFoundry平台上的nodejs应用
网络上关于如何本地调试nodejs应用的教程已经很多了,工具有Chrome开发者工具,Visual Studio Code,和nodejs周边的一些小工具等等. 在实际情况中,我们可能遇到本地运行良好 ...
- C++手动调用析构函数无效问题排查
在学习C++的时候,都知道不要手动调用析构函数,也不要在构造函数.析构函数里调用虚函数.工作这么多年,这些冷门的知识极少用到,渐渐被繁杂的业务逻辑淹没掉. 不过,最近项目里出现了析构函数没有被正确地调 ...
- java 日期。时间
友情链接: https://www.cnblogs.com/wanson/articles/10818955.html
- Django—model系统:ORM之其他骚操作
Django ORM执行原生SQL # extra # 在QuerySet的基础上继续执行子语句 # extra(self, select=None, where=None, params=None, ...
- 初级文件IO——若干种文件共享操作 如何影响 文件文件描述符表
同一进程共享操作相同的文件 在同一个进程中多次open打开同一文件时,文件描述符可能会相同吗? 答:不可能.在同一进程里面,一旦某个文件描述符被用了,在close释放之前,别人不可能使用,所以指向同一 ...
- Django阶段总结与Ajax
一.路由控制 二.视图层 三.模板层 四.模型层.单表操作.多表操作 五.什么是ajax 一.路由控制 补充点(什么是web应用?) 网站:BS架构应用程序:B是浏览器 S:server(实现了ws ...