1 条题解

  • 0
    @ 2026-5-6 18:36:31

    又来了又来了,又是思维 800 代码 2800。别放这种题了好不好求求你了欧内该/dk

    首先有几个很显然的结论:

    如果有一条路径经过一个权值 xor 不是 0 的环,则一定无解(可以无限绕这个环)

    如果有一条路径经过一个权值 xor 是 0 的环,则该路径 xor 必须是 0 否则无解(同理)

    考虑如何处理这样的环,发现很自然可以考虑 dfs 树,在树上打一个 tag 表示从树根到现在的位置的 xor,然后判断 dfs 树上的返祖边和这条边的起点与终点的 xor 即可处理出这些环,再从根往下 dfs 一次即可判断到终点的路径是否存在无解情况。

    处理掉环之后剩下的有解情况一定是一张 dag(xor 是 0 的环可以等同于不可以经过),在其之上求出答案是简单的。

    精细实现的话可以做到 O(n)O(n),有点懒就写了 O(nlogn)O(n\log n),无伤大雅啦。

    #include<bits/stdc++.h>
    using namespace std;
    #define LL long long
    struct edge{
    	LL to,nt,val;
    }a[200005],b[200005];
    LL n,i,j,k,m,cnt=0,t,x,y,z,cnt1=0;
    LL nxt[200005],num[200005],depth[200005],deg1[200005],deg2[200005],nxt1[200005];
    LL fa[200005][22];
    LL val1[200005],val2[200005],tmp1[200005],tmp2[200005],fa1[200005];
    bool flag[200005],vis[200005],tag[200005],flag1[200005],flag2[200005],flag3[200005],flag4[200005];
    queue<LL> q;
    stack<LL> st1[200005],st2[200005];
    void add(LL x,LL y,LL z){
    	a[++cnt].to=y;a[cnt].nt=nxt[x];nxt[x]=cnt;a[cnt].val=z;
    }
    void add1(LL x,LL y,LL z){
    	b[++cnt1].to=y;b[cnt1].nt=nxt1[x];nxt1[x]=cnt1;b[cnt1].val=z;
    }
    LL father(LL x){
    	if(fa1[x]==x) return x;
    	else return fa1[x]=father(fa1[x]);
    }
    bool check(LL x,LL y){
    	if(depth[x]<depth[y]) return false;
    	LL num=depth[x]-depth[y];
    	for(LL i=0;i<=20;i++)
    	  if(num&(1ll<<i)) x=fa[x][i];
    	if(x==y) return true;
    	else return false;
    }
    void update(LL x,LL y,LL val){
    	if(flag2[x]==true) flag2[y]=true;
    	if(flag3[x]==true) flag3[y]=true;
    	if(tmp1[x]!=-1){
    		if(tmp1[y]!=-1 && (tmp1[x]^val)!=tmp1[y]) flag3[y]=true;
    		if(tmp1[y]==-1) tmp1[y]=tmp1[x]^val;
    	}
    	if(tmp2[x]!=-1){
    		if(tmp2[y]!=-1 && (tmp2[x]^val)!=tmp2[y]) flag2[y]=true;
    		if(tmp2[y]==-1) tmp2[y]=tmp2[x]^val;
    	}
    }
    void dfs(LL x){
    	for(LL i=nxt[x];i;i=a[i].nt)
    	  if(flag[a[i].to]==false){
    	  	flag[a[i].to]=true,num[a[i].to]=num[x]^a[i].val,depth[a[i].to]=depth[x]+1;
    	  	vis[i]=true;
    	  	LL now=x;fa[a[i].to][0]=x;
    	  	for(LL j=1;j<=20;j++)
    	  	  now=fa[now][j-1],fa[a[i].to][j]=now;
    	  	dfs(a[i].to);
    	  }
    }
    void dfs1(LL x){
    	if(x==y){
    		return ;
    	}
    	for(LL i=nxt[x];i;i=a[i].nt){
    		if(flag[a[i].to]==false && flag1[a[i].to]==false) flag[a[i].to]=true,dfs1(a[i].to);
    		if(tag[a[i].to]==true && flag1[a[i].to]==false) tag[x]=true,deg1[a[i].to]++,deg2[x]++;
    	}
    }
    LL dfs2(LL fath,LL x){
    	LL maxx=0;
    	for(LL i=nxt[x];i;i=a[i].nt){
    		if(vis[i]==true){
    	  		maxx=max(maxx,dfs2(x,a[i].to));
    	  	}
    	  	else{
    	  		if(check(x,a[i].to)==true){
    	  			maxx=max(maxx,depth[x]-depth[a[i].to]+1);
    				if((num[x]^a[i].val)!=num[a[i].to]) flag2[x]=true;
    			}
    		}
    	}
    	if(maxx>0){
    		flag1[x]=true;
    		if(maxx>1) fa1[x]=fath;
    		maxx--;
    	}
    	return maxx;
    }
    void doit(LL x){
    	if(flag1[x]==true){
    		if(flag3[x]==true) flag2[x]=true;
    		if(tmp1[x]!=-1 && tmp2[x]!=-1 && tmp1[x]!=tmp2[x]) flag2[x]=true;
    		if(tmp1[x]!=-1) tmp2[x]=tmp1[x];
    		tmp1[x]=-1;
    	}
    }
    void dfs4(LL x){
    	doit(x);
    	for(LL i=nxt[x];i;i=a[i].nt){
    		if(vis[i]==true) st1[x].push(i);
    		else if(check(x,a[i].to)==false) st2[x].push(i);
    	}
    	while(!st2[x].empty()){
    		update(x,a[st2[x].top()].to,a[st2[x].top()].val),doit(a[st2[x].top()].to);
    		st2[x].pop();
    	} 
    	while(!st1[x].empty()){
    	  	update(x,a[st1[x].top()].to,a[st1[x].top()].val);
    	  	doit(a[st1[x].top()].to);
    	  	dfs4(a[st1[x].top()].to);
    	  	st1[x].pop();
    	} 
    } 
    void dfs5(LL x){
    	if(flag2[x]==true) flag2[y]=true;
    	for(LL i=nxt1[x];i;i=b[i].nt)
    	  if(flag4[b[i].to]==false){
    	  	flag4[b[i].to]=true;dfs5(b[i].to);
    	  }
    }
    int main(){
    	scanf("%lld",&t);
    	while(t--){
    		cnt=0,cnt1=0;
    		for(i=1;i<=n;i++){
    			nxt[i]=nxt1[i]=depth[i]=num[i]=deg1[i]=deg2[i]=val1[i]=val2[i]=tmp1[i]=tmp2[i]=0;
    			flag[i]=tag[i]=false,flag1[i]=flag2[i]=flag3[i]=flag4[i]=false;
    			while(!st1[i].empty()) st1[i].pop();while(!st2[i].empty()) st2[i].pop();
    		}
    		for(i=1;i<=m;i++)
    		  vis[i]=false;
    		for(i=1;i<=n;i++)
    		  for(j=0;j<=20;j++)
    		    fa[i][j]=0;
    		scanf("%lld%lld",&n,&m);
    		for(i=1;i<=n;i++)
    		  tmp1[i]=-1,tmp2[i]=-1; 
    		for(i=1;i<=m;i++){
    			scanf("%lld%lld%lld",&x,&y,&z),add(x,y,z),add1(y,x,z);
    		}
    		  
    		scanf("%lld%lld",&x,&y);
    		tmp1[x]=0;
    		flag[x]=true;dfs(x);
    		for(i=1;i<=n;i++)
    		  fa1[i]=i;
    		dfs2(0,x);
    		for(i=1;i<=n;i++)
    		  if(flag2[i]==true) flag2[father(i)]=true;
    		for(i=1;i<=n;i++)
    		  if(flag2[father(i)]==true) flag2[i]=true;
    		dfs4(x);
    		if(tmp2[y]>0) flag2[y]=true;
    		dfs5(y);
    		if(flag2[y]==true) printf("-1\n");
    		else{
    			for(i=1;i<=n;i++)
    			  flag[i]=false;
    			tag[y]=true;flag[y]=true;
    			dfs1(x);tag[x]=true;
    			while(!q.empty()) q.pop();
    			q.push(x);val1[x]=1;
    			while(!q.empty()){
    				LL tmp=q.front();q.pop();
    				for(LL i=nxt[tmp];i;i=a[i].nt)
    				  if(deg1[a[i].to]>0){
    					val1[a[i].to]^=val1[tmp];
    					deg1[a[i].to]--;if(deg1[a[i].to]==0) q.push(a[i].to);
    				}
    			}
    			while(!q.empty()) q.pop();
    			q.push(y);val2[y]=1;
    			while(!q.empty()){
    				LL tmp=q.front();q.pop();
    				for(LL i=nxt1[tmp];i;i=b[i].nt)
    				  if(deg2[b[i].to]>0){
    					val2[b[i].to]^=val2[tmp];
    					deg2[b[i].to]--;if(deg2[b[i].to]==0) q.push(b[i].to);
    				}
    			}
    			LL ans=0;
    			for(LL i=1;i<=n;i++)
    			  if(tag[i]==true){
    			  	for(LL j=nxt[i];j;j=a[j].nt)
    			  	  if(tag[a[j].to]==true && val1[i]==1 && val2[a[j].to]==1) ans^=a[j].val;
    			  }
    			printf("%lld\n",ans);
    		}
    	}
    	return 0;
    }
    
    
    • 1

    信息

    ID
    11051
    时间
    3000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者