zoukankan      html  css  js  c++  java
  • 【BZOJ】2115: [Wc2011] Xor

    【题意】给定n个点m条边的无向连通图,每条边有非负边权wi,求从1到n的路径,使得路径上的边权异或和最大。n,m<=10^5,wi<=10^18。
    路径可以重复经过边和点,图有重边
    【算法】线性基+无向图DFS找环
    【题解】参考ljh2000の博客
    答案由1~n的任意一条通路和若干个环组成。

    • 环:因为走到某个点后返回没有价值,所以必须是环才能有贡献。一个环的权值可以通过从1到达这个环遍历一圈后返回来得到。
    • 任意通路:如果要更换一条1到n的路径,那么和原路径会形成一个环,相当于异或这个环。

    这样之后就明确了需要找到一条1~n的通路和所有环的异或值,将这些异或值构造线性基后从大到小贪心贡献答案即可。
    现在需要求无向连通图的所有环,由于有重边为了方便每条边也算一个环,可证总数不超过2m个。DFS全图,标记vis不回溯,访问到标记过的点就算一个环,这样可以不重不漏地统计到全图所有的环。
    复杂度O(m log wi)。

    #include<cstdio>
    #include<algorithm>
    #define int long long
    using namespace std;
    const int maxn=100010;
    int n,m,d[maxn],first[maxn],tot,cir[maxn*2],cnt,b[maxn];
    bool vis[maxn];
    struct edge{int v,w,from;}e[maxn*2];
    void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
    void dfs(int x){//you chong bian,bu neng ji "fa".
    	vis[x]=1;
    	for(int i=first[x];i;i=e[i].from){
    		if(!vis[e[i].v]){d[e[i].v]=d[x]^e[i].w;dfs(e[i].v);}
    		else cir[++cnt]=d[x]^d[e[i].v]^e[i].w;
    	}
    }
    #undef int
    int main(){
    #define int long long
    	scanf("%lld%lld",&n,&m);
    	for(int i=1;i<=m;i++){
    		int u,v,w;
    		scanf("%lld%lld%lld",&u,&v,&w);
    		insert(u,v,w);insert(v,u,w);
    	}
    	dfs(1);
    	int ans=d[n];
    	for(int i=1;i<=cnt;i++){
    		for(int j=62;j>=0;j--)if(cir[i]>>j){
    			if(b[j])cir[i]^=b[j];else{b[j]=cir[i];break;}
    		}
    	}
    	for(int i=62;i>=0;i--)if((ans^b[i])>ans)ans^=b[i];
    	printf("%lld",ans);
    	return 0;
    }
    

    有另一道类似的题目:
    【CodeForces】724G Xor-matic Number of the Graph
    【题意】给定一个边权非负的无向图,定义三元组 (u, v, s) 为有趣的,当且仅当u、v(1 ≤ u < v ≤ n)间存在一条路径异或和为s,允许经过重复点、重复边。求所有有趣的三元组的s之和。
    【题解】构造DFS树,将所有环权加入线性基。求和问题,依次考虑每一位的贡献。假设当前考虑点对(x,y)的第z位。
    如果第z位相同,那么需要选择的环组合第z位为1。如果线性基中所有数字第z位都为0则无贡献,否则任选一个第z位为1的数字,其余数字任意组合后根据第z位的01来确定是否异或这个数字。设线性基的数字个数为k,则有(2^{k-1})种方案。
    要求为0的话,如果全0任意贡献,否则选择一个1,其余任意。

  • 相关阅读:
    jquery实现选项卡(两句即可实现)
    常用特效积累
    jquery学习笔记
    idong常用js总结
    织梦添加幻灯片的方法
    LeetCode "Copy List with Random Pointer"
    LeetCode "Remove Nth Node From End of List"
    LeetCode "Sqrt(x)"
    LeetCode "Construct Binary Tree from Inorder and Postorder Traversal"
    LeetCode "Construct Binary Tree from Preorder and Inorder Traversal"
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8992047.html
Copyright © 2011-2022 走看看