zoukankan      html  css  js  c++  java
  • [NOI.AC#41]最短路 线性基

    链接

    题解

    如果不加边,两个点之间的长度是唯一的(只能走最短路径),因为如果重复走,就异或掉了。

    因此,先DFS预处理一下每个点到根的距离 (d[x]) ,那么 (x,y) 之间的距离为 $d[x] oplus d[y] $

    对于每条新建的边 ((u,v,w)) ,它实际上增加了一个环,如果没有范围限制,那就变成了[WC2011]最大XOR和路径(BZOJ2115)。

    按照它的思路,我们对每个环(权值为 (W[i]=d[u[i]]oplus d[v[i]]oplus w[i]))构造线性基,考虑如何保证满足范围限制

    将询问离线,并根据右端点排序(挂链表),然后按顺序扫描边数组 (W[i]) ,对于二进制基底 (p[i]) ,定义 (q[i]) 为它的位置,显然为了满足范围限制, (q[i]) 越大越好。因此从大到小枚举 (i) ,每遇到一个 (q[i]) 比当前位置小的,我们将其与之交换,然后多出来的 (p[i]) 再往下插入线性基。

    处理答案时,从高位向低位贪心,如果 (q[i]) 在范围内就可以加入。

    #include<bits/stdc++.h>
    #define REP(i,a,b) for(int i(a);i<=(b);++i)
    #define dbg(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;
    typedef long long ll;
    typedef unsigned int uint;
    typedef unsigned long long ull;
    typedef pair<int,int>pii;
    template<typename T,typename U>inline char smin(T&x,const U&y){return x>y?x=y,1:0;}
    template<typename T,typename U>inline char smax(T&x,const U&y){return x<y?x=y,1:0;}
    namespace IOManager{
    	const unsigned int iSize(131072),oSize(65536);
    	char buf[iSize],wbuf[oSize+128],*iT=buf+iSize,*iS=iT-1,*oS=wbuf-1,*oT=wbuf+oSize;
    	struct FastIO{
    		inline char gc(){
    			if(++iS==iT)fread(iS=buf,1,iSize,stdin);return *iS;
    		}
    		template<typename T>
    			inline void read(T&w){register char c,p=0;
    				while(isspace(c=gc()));if(c=='-')p=1,c=gc();w=c^48u;
    				while(isdigit(c=gc()))w=w*10+(c^48u);if(p)w=-w;
    			}
    		inline int read(){register int x;return read(x),x;}
    		inline void flush(){fwrite(wbuf,1,oS-wbuf+1,stdout);oS=wbuf-1;}
    		~FastIO(){flush();}
    		inline FastIO&operator<<(const char&c){if(oS>oT)flush();*++oS=c;}
    		inline void putstr(const string&s){
    			const int l=s.length();
    			if(oS>oT)flush();
    			for(int i=0;i<l;++i)*++oS=s[i];
    		}
    		template<typename T>
    			inline FastIO&operator<<(T x){
    				static char stk[30];int top=0;
    				if(oS>oT)flush();
    				if(x==0)return *++oS='0',*this;
    				if(x<0)x=-x,*++oS='-';
    				for(;x;x/=10)stk[++top]=x%10^48;
    				while(top)*++oS=stk[top--];
    				return*this;
    			}
    	};
    }IOManager::FastIO io;
    #define read io.read
    const int n=read(),m=read(),Q=read(),N=3e5+5;
    vector<int>g[N];
    int head[N],tot,d[N],w[N],r[N],l[N],p[33],q[33],ans[N];
    struct node{int v,w,nxt;}e[N<<1];
    inline void add(int x,int y,int z){e[++tot]=(node){y,z,head[x]};head[x]=tot;}
    inline void dfs(int x,int fa){for(int i=head[x];i;i=e[i].nxt)if(e[i].v!=fa)d[e[i].v]=d[x]^e[i].w,dfs(e[i].v,x);}
    int main(){
    	REP(i,2,n){
    		int x=read(),y=read(),z=read();
    		add(x,y,z),add(y,x,z);
    	}
    	dfs(1,0);
    	REP(i,1,m)w[i]=d[read()]^d[read()]^read();
    	REP(i,1,Q){
    		ans[i]=d[read()]^d[read()];l[i]=read();g[read()].push_back(i);
    	}
    	REP(t,1,m){
    		int x=w[t],r=t;
    		for(int i=30;~i;--i)if(x>>i&1){
    			if(!p[i]){p[i]=x,q[i]=r;break;}
    			if(q[i]<r)swap(p[i],x),swap(q[i],r);
    			x^=p[i];
    		}
    		for(int k:g[t])for(int i=30;~i;--i)if(q[i]>=l[k])smin(ans[k],ans[k]^p[i]);
    	}
    	REP(i,1,Q)io<<ans[i]<<'
    ';
    	return 0;
    }
    
    
  • 相关阅读:
    时隔 4 年!ElasticJob 3.0.0 发布,王者归来。。
    Git 代码防丢指南,再也不怕丢失代码了!
    排查线上问题必须掌握的 6 个 Linux 命令!
    Leaflet添加图片图层:ImageOverlay
    js图片数据流
    arcgis查找与要素相交的内容 by 空间连接查询
    Leaflet添加图片图层:使用Axios请求arcgis server rest api的exportmap,获取图片并进行显示
    esri-leaflet: unique value renderer唯一值渲染-dynamiclayers参数
    arcgis server缓存切片
    城市给排水法律法规
  • 原文地址:https://www.cnblogs.com/HolyK/p/9852060.html
Copyright © 2011-2022 走看看