[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;
}

原文地址:https://www.cnblogs.com/HolyK/p/9852060.html