BZOJ 2115 异或线性基+DFS找环
2017-09-07 21:22
106 查看
题目链接
题意:给定一个n个点,m条边的无向图,求出一条1−>n节点的路径,使得路径上经过的边的权值的异或和最大。
思路:
解决此题只需要基于一个事实:
任意一条1−>n的路径的异或和都可以由任意一条1−>n的路径和与图中一些环的异或和组合而成。
为什么呢?
简单画个图,举个例子~:
考虑下面的这个图,n=8 m=9,存在3个环,标号1,2,3
可见从1−>8有3条路径。
对于任意的一条,比如说:1−>5−>6−>7−>8
当该路径异或上标号2这个环:1−>5−>6−>7−>4−>2−>1
易发现,路径1−>5−>6−>7异或上了两次,故直接抵消,剩下的路径异或为:
1−>2−>4−>7−>8
刚好为第二条路径。
同理,当该路径异或上标号3这个环,就得到了最下面的1−>n的路径。
故易发现:对于一个经过某路径的环来说,一定是从某个点u出发形成两条路径,最后两条路径又一定会在一个点v相聚,故异或上一个环,就相当于对于u−>v这个过程,走另外的一条路。
那没有经过路径的环呢?比如1−>5−>6−>7−>8和环1。
对于这种情况,我们可以看成我们先到那个环走上一圈,再原路返回,这样从起点到环的路径走了两次,异或后为0,剩下的异或和就只剩环的异或和。
对于上面的情况,异或上环1就相当于我们从1出发,绕环1一圈,回到1之后再走路径1−>5−>6−>7−>8到达终点。
故我们可以找出图中的所有的环的异或和,构建其异或线性基,然后对于一条任意的从1−>n的路径异或和dis[n],从大到小枚举线性基,若能使dis[n]增大,则加上其贡献。
至此,大功告成。
代码:
题意:给定一个n个点,m条边的无向图,求出一条1−>n节点的路径,使得路径上经过的边的权值的异或和最大。
思路:
解决此题只需要基于一个事实:
任意一条1−>n的路径的异或和都可以由任意一条1−>n的路径和与图中一些环的异或和组合而成。
为什么呢?
简单画个图,举个例子~:
考虑下面的这个图,n=8 m=9,存在3个环,标号1,2,3
可见从1−>8有3条路径。
对于任意的一条,比如说:1−>5−>6−>7−>8
当该路径异或上标号2这个环:1−>5−>6−>7−>4−>2−>1
易发现,路径1−>5−>6−>7异或上了两次,故直接抵消,剩下的路径异或为:
1−>2−>4−>7−>8
刚好为第二条路径。
同理,当该路径异或上标号3这个环,就得到了最下面的1−>n的路径。
故易发现:对于一个经过某路径的环来说,一定是从某个点u出发形成两条路径,最后两条路径又一定会在一个点v相聚,故异或上一个环,就相当于对于u−>v这个过程,走另外的一条路。
那没有经过路径的环呢?比如1−>5−>6−>7−>8和环1。
对于这种情况,我们可以看成我们先到那个环走上一圈,再原路返回,这样从起点到环的路径走了两次,异或后为0,剩下的异或和就只剩环的异或和。
对于上面的情况,异或上环1就相当于我们从1出发,绕环1一圈,回到1之后再走路径1−>5−>6−>7−>8到达终点。
故我们可以找出图中的所有的环的异或和,构建其异或线性基,然后对于一条任意的从1−>n的路径异或和dis[n],从大到小枚举线性基,若能使dis[n]增大,则加上其贡献。
至此,大功告成。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int A = 5e4 + 10; class Gra{ public: int v,next;ll w; }G[A<<2]; int head[A],tot,twt,n,m; ll dis[A],a[A<<2],b[110]; bool vis[A]; void add(int u,int v,ll w){ G[tot].v = v; G[tot].w = w; G[tot].next = head[u]; head[u] = tot++; } void dfs(int u,int pre){ vis[u] = 1; for(int i=head[u] ;i!=-1 ;i=G[i].next){ int v = G[i].v;ll w = G[i].w; if(v == pre) continue; if(!vis[v]){ dis[v] = dis[u] ^ w; dfs(v,u); } else a[++twt] = dis[u]^dis[v]^w; } } void init_Xor(){ for(int i=1 ;i<=twt ;i++) for(int j=62 ;j>=0 ;j--){ if(a[i]>>j & 1){ if(b[j]) a[i] ^= b[j]; else{ b[j] = a[i]; for(int k=j-1 ;k>=0 ;k--) if(b[k] && (b[j]>>k&1)) b[j] ^= b[k]; for(int k=j+1 ;k<=62;k++) if(b[k]>>j&1) b[k] ^= b[j]; break; } } } } int main(){ memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(int i=1 ;i<=m ;i++){ int u,v;ll w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w);add(v,u,w); } dfs(1,1);init_Xor(); for(int i=62 ;i>=0 ;i--) if((dis ^b[i]) > dis ) dis ^=b[i]; printf("%lld\n",dis ); return 0; }
相关文章推荐
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- bzoj 2115: [Wc2011] Xor【线性基+dfs】
- BZOJ 2115: [Wc2011] Xor (dfs + gauss 线性基 异或最长路)
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ 2115 Xor(dfs&独立回路&异或消元)
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- BZOJ2115 线性基 对于异或环的处理
- 【bzoj4017】小Q的无敌异或 树状数组
- 【bzoj4561】【JLOI2016】【圆的异或并】【扫描线+set】
- bzoj 4561: [JLoi2016]圆的异或并 (计算几何+扫描线+splay)