题目链接

题意 : 给出一副简单图、要你找出一个回路、使得其路径上边权的异或和最大

分析 :

类似的题有 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+时间戳搜独立回路、线性基 )相关推荐

  1. hdu 5544 Ba Gua Zhen

    link 因为在沈阳站的比赛中我们没有做出来H题,后来才知道是高斯消元.于是我先来补一下高斯消元的题目.先做了hdu XOR对线性基有了一定的了解,然后来做一下南阳ccpc的Ba Gua Zhen 分 ...

  2. hdu 5544 Ba Gua Zhen(线性基+dfs)

    题意: 一个无向图,每条边有值,找出无向图中所有的环的异或和,问这些值能异或出来的最大值. 解题思路: 去年的做的比赛里的题,今年才补上. 找环用dfs跑一遍图就可以找出来了,然后求最大的异或和,这是 ...

  3. [HDU] 5544 Ba Gua Zhen

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5544 题目大意:T组数据, 给一个n个点, m条边的无向连通图, 无自环, 无重边, 求最大XOR回 ...

  4. HDU 5544 Ba Gua Zhen (dfs独立回路异或消元)

    这道题和BZOJ 2115 基本一样,容易一点,直接存个代码:这个代码要好看一点(好像并没有什么区别...) #include <bits/stdc++.h> #define LL lon ...

  5. 2015南阳CCPC E - Ba Gua Zhen 高斯消元 xor最大

    Ba Gua Zhen Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 无 Description During the Three-Kingdom perio ...

  6. Ba Gua Zhen

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5544 学习链接:https://www.cnblogs.com/qscqesze/p/4902518. ...

  7. hdu5544 Ba Gua Zhen(高斯消元)

    思路:首先DFS把图上的所有环找出来,然后就是K个数里面任意选数使得异或和最大,高斯消元就好了 异或方程的高斯消元见 点击打开链接 #include<bits/stdc++.h> usin ...

  8. UESTC OJ1219 Ba Gua Zhen

    链接:http://mozhu.today/#/problem/show/1219 题意:给定n个点m条边有边权的无向图,求一个异或值最大的回路. 分析:其实就是将所有环的异或值找出来然后任选一些组成 ...

  9. HDU 3949 XOR 线性基

    http://acm.hdu.edu.cn/showproblem.php?pid=3949 求异或第k小,结论是第k小就是 k二进制的第i位为1就把i位的线性基异或上去. 但是这道题和上一道线性基不 ...

最新文章

  1. 作为零基础如何自学软件测试?
  2. 基于visual Studio2013解决面试题之0608找出两个只出现一次的数
  3. 风格迁移--U-GAT-IT模型(ICLR 2020)
  4. 从0到1设计一个秒杀系统
  5. jquery实现图片等比例缩放,解决max-width在ie中不兼容问题
  6. java 蓝桥杯算法训练 sign函数
  7. MVC实用架构设计(三)——EF-Code First(4):数据查询
  8. html音乐播放标签,html5 视频和音乐播放器标签属性
  9. element ui 弹窗在IE11中关闭时闪现问题修复
  10. 如何修改计算机mac,超简单的电脑mac地址查看和修改方法
  11. 交通信号灯的检测与识别
  12. 做毕业论文时遇见的问题
  13. $.ajax %5b%5d,数据传回后台数带有%5B%5D的问题
  14. 《庄子·内篇·逍遥游第一》
  15. SEO与SEM区别是什么
  16. [附源码]Python计算机毕业设计电影票购票系统
  17. 出现“连接到服务器失败。错误: 0x80080005”错误的解决办法
  18. android imageview 锯齿,[置顶] android 自定义圆角ImageView以及锯齿的处理
  19. 计算机 我们一起学猫叫歌词,猫叫是什么歌 抖音我们一起学猫叫完整版歌词
  20. win10键盘全部没反应_win10笔记本键盘全部没反应 win10键盘全部没反应解决方法...

热门文章

  1. PlantSimulation切换中文的方法
  2. SQL*Plus 学习笔记——常用编辑命令
  3. Java日期和时间JDK—API1.6.0(Date类、Calendar类)
  4. JAVA SE 是什么? 入门级讲解。
  5. HTML5QQ登录cav demo
  6. 输入一个华氏温度,要求输出摄氏温度。公式为 c=5(F-32)/9 输出要求有文字说明,取位2小数。...
  7. 《实战Java高并发程序设计》github笔记和源码
  8. 智慧大脑的搭建在智慧工地管理系统中有何作用
  9. tensorflow玻尔兹曼机_受限玻尔兹曼机(Restricted Boltzmann Machine)
  10. 配置Eureka时Status显示的是电脑名而不是localhost及ipAddr显示为本机ip的问题