zoukankan      html  css  js  c++  java
  • [WC2011]最大XOR和路径

    [WC2011]最大XOR和路径

    给出一有n个点m条变的无向联通图,定义路径长度为路径上的边权的异或和,询问从起点1到终点n的最大路径长度,(n≤50000,m≤100000)

    注意到异或和问题,即使已经可以向线性基靠了,之所以为何会推出一下结论,笔者猜测是把线性空间与图论对比,而有考虑到图论中最重要的环,在加上对链的考虑,因为你必须要有一条链从起点达到终点。

    先介绍一下结论

    1. 从任意一个点出发到达任意一个点原路返回没有影响,这个显然,因为异或把中间的路径异或掉了,可以理解成瞬间移动,移动到一个点,做了一些事情,再返回,忽略中间过程。

    2. 进入一个环,不走完等于没走,显然根据结论1,原路返回等于没走,于是联系结论1,易知,瞬间移动的目的在于进入一个环,收取边权,于是不难得知问题关键在于环。

    3. 对于还套环,我们只能走完,只能走其中一个子环,如图,显然从任何一个地方进来,再回到原点出去,必然是其中一个子环,而把一些子环的路径长度加入线性基,必然也可以通过这些子环异或出其他的子环的路径长度,即环的类异或性。

    4. 对于任意一条确定了起点和终点的路径,它的路径变换可以通过与环的异或改变,如图中路径1->2->3,异或上最大的环就是1->4->3。

    总上这些结论,我们只要dfs把所有的环加入线性基,而选择一条必须选的链与线性基求最大异或和,而求最大异或和的过程包含了对路径的改变,以及瞬间移动获取环上的边权和还套环中环与环的选择,于是可以证明这种做法的正确性。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #define il inline
    #define ri register
    #define ll long long
    #define Size 60000
    using namespace std;
    struct base{
    	ll b[64];
    	il void insert(ll x){
    		for(ri int i(63);i>=0;--i)
    			if(x>>i){
    				if(b[i])x^=b[i];
    				else return(void)(b[i]=x);
    			}
    	}
    	il ll ask(ll x){
    		for(ri int i(63);i>=0;--i)
    			if((x^b[i])>x)x^=b[i];
    		return x;
    	}
    }B;
    struct point{
    	point*next;int to;ll w;
    }*head[Size];
    ll dis[Size];
    bool check[Size];
    void dfs(int);
    il void link(int,int,ll);
    template<class free>
    il void read(free&);
    int main(){
    	int n,m,u,v;ll w;read(n),read(m);
    	while(m--)read(u),read(v),read(w),
    				  link(u,v,w),link(v,u,w);
    	dfs(1),printf("%lld",B.ask(dis[n]));
    	return 0;
    }
    void dfs(int x){
    	check[x]|=true;
    	for(point *i(head[x]);i!=NULL;i=i->next)
    		if(check[i->to])B.insert(dis[i->to]^dis[x]^i->w);
    		else dis[i->to]=dis[x]^i->w,dfs(i->to);
    }
    il void link(int u,int v,ll w){
    	head[u]=new point{head[u],v,w};
    }
    template<class free>
    il void read(free &x){
    	x^=x;ri char c;while(c=getchar(),c<'0'||c>'9');
    	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
  • 相关阅读:
    10. 正则表达式匹配
    5. 最长回文子串
    板子总结
    2020: 学生查询
    解决apt-get出错
    03如何计算算法的复杂度
    ad如何从PCB中导出元件封装库
    调车遇到的问题及解决办法
    java报错与解决方法总结
    SWD下载k60
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/10874642.html
Copyright © 2011-2022 走看看