zoukankan      html  css  js  c++  java
  • bzoj2115 Xor

    题目链接

    problem

    考虑一个边权为非负整数的无向连通图,节点编号为(1)(N),试求出一条从 (1) 号节点到 (N) 号节点的路径,使得路径上经过的边的权值的 (XOR) 和最大。

    路径可以重复经过某些点或边,当一条边在路径中出现了多次时,其权值在计算 (XOR) 和时也要被计算相应多的次数,具体见样例。

    solution

    考虑先确定一条从(1)(n)的不含环的路径。

    enter description here

    如图,我们先选择(1-2-3-4-9-10)这条路径,然后发现,我们在3这个位置可以通过(3-5)这条边,去环里面转一圈,然后再回来。因为(3-5)这条边走了两边。所以增加的边权就是这个环的异或和。

    这个我们就可以猜想了。我们先选择任意一个可以从(1-n)的路径,称之为链。然后该图中所有的环都是可以产生贡献的。所以我们把这条链的异或和和各个环的异或和全部扔到线性基里去。然后求最大值就行了。

    为什么这条链可以任意选呢。因为如果有其他的路径可以到达(n),必定与该链形成了环。只要选择那个环就相当于走了另外一条路径。

    如图

    enter description here

    我们可以选择以(1-2-3-4-9-10)或者是(1-2-3-4-11-12-13-9-10)作为链。
    不管以哪一条为链只要异或上这个蓝色的环。就会变成另外一条链。

    code

    /*
    * @Author: wxyww
    * @Date:   2019-07-23 14:59:35
    * @Last Modified time: 2019-07-23 15:09:13
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    using namespace std;
    typedef long long ll;
    const int N = 100100;
    #define int ll
    ll read() {
    	ll x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    struct node {
    	int v,nxt;ll w;
    }e[N << 1];
    int head[N],ejs;
    void add(int u,int v,int w) {
    	e[++ejs].v = v;e[ejs].w = w;e[ejs].nxt = head[u];head[u] = ejs;
    }
    int vis[N];
    ll dis[N],p[N];
    void ins(ll x) {
    	for(int i = 63;i >= 0;--i) {
    		if(!(x >> i & 1)) continue;
    		if(!p[i]) {
    			p[i] = x;break;
    		}
    		else x ^= p[i];
    	}
    }
    ll query(ll x) {
    	ll ans = x;
    	for(int i = 63;i >= 0;--i) if((ans ^ p[i]) > ans) ans ^= p[i];
    	return ans;
    }
    void dfs(int u,int father) {
    	vis[u] = 1;;
    	for(int i = head[u];i;i = e[i].nxt) {
    		int v = e[i].v;
    		if(v == father) continue;
    		if(vis[v]) {
    			ins(dis[u] ^ e[i].w ^ dis[v]);continue;
    		}
    		else dis[v] = dis[u] ^ e[i].w,dfs(v,u);
    	}
    }
    
     main() {
    	int n = read(),m = read();
    	for(int i = 1;i <= m;++i) {
    		int u = read(),v = read();ll w = read();
    		add(u,v,w);add(v,u,w);
    	}
    	dfs(1,0);
    	cout<<query(dis[n]);
    	return 0;
    }
    
  • 相关阅读:
    JS数据类型、JS数据类型转换、JS运算
    JS 变量
    js初识 何为JavaScript
    ES6 字符串的用法
    ES6 初识 let、const、ES6兼容、解构赋值
    Bootstrap 小结
    列一下我所认为的,你面试微软前必须要读的十本书[转]
    MFC中换行实现
    MFC中输入框的文本转换为char[]字符数组类型
    MFC下OpenGL入门(可以用)
  • 原文地址:https://www.cnblogs.com/wxyww/p/bzoj2115.html
Copyright © 2011-2022 走看看