题解:P11644 【MX-X8-T3】「TAOI-3」地地爱打卡

前言

诈骗题。

思路分析

首先异或啥的别看了,是假的。

考虑如果要求异或值为 x,如果我们能得到的路径长度为 k,考虑:

  • xk,那么可以将 kx 的部分分成两半抵消;

  • x>k,那么可以从 s 出发走到任意一个点再沿反边返回,每次增加 2 的路径长度。

所以,只需要保证 xk 的奇偶性相同就行了。

那么直接做就行了。

  • 如果 st 不连通,没戏;

  • 如果 st 所在的连通块是二分图,那么看 st 是否同色,判断两点之间路径的奇偶性;

  • 如果 st 所在的连通块不是二分图,那么两点之间一定同时存在奇偶路径。

除此之外,还需要特判 s=t 的情况。

使用并查集和二分图染色实现,总体复杂度 O(nα(n))

#include<bits/stdc++.h>
using namespace std;
int n,m,q,x,y,k,flag;
int head[200005],nxt[600005],target[600005],tot;
void add(int x,int y){
	tot++;
	nxt[tot]=head[x];
	head[x]=tot;
	target[tot]=y;
}
int fa[200005],col[200005],siz[200005];
void init(){
	for(int i=1;i<=n;i++){
		fa[i]=i;
		col[i]=2;
		siz[i]=1;
	}
}
int find(int x){
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]);
}
void merge(int x,int y){
	x=find(x);
	y=find(y);
	if(x==y) return;
	fa[x]=y;
	siz[y]+=siz[x];
}
void dfs1(int x){
	for(int i=head[x];i;i=nxt[i]){
		int y=target[i];
		if(col[y]==2){
			col[y]=(!col[x]);
			dfs1(y);
		}else if(col[x]==col[y]) flag=true;
	}
}
void dfs2(int x){
	col[x]=-1;
	for(int i=head[x];i;i=nxt[i]){
		int y=target[i];
		if(col[y]==-1) continue;
		dfs2(y);
	}
}
signed main(){
	cin>>n>>m>>q;
	init();
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		add(x,y);
		add(y,x);
		merge(x,y);
	} 
	for(int i=1;i<=n;i++){
		if(col[i]==2){
			flag=false;
			col[i]=0;
			dfs1(i);
			if(flag) dfs2(i);
		}
		
	}
	for(int i=1;i<=q;i++){
		cin>>x>>y>>k;
		if(find(x)!=find(y)){
			cout<<"expand"<<'\n';
		}else{
			if(x==y && siz[find(x)]==1){
				if(k) cout<<"expand"<<'\n';
				else cout<<"tribool"<<'\n';
			}else{
				if(col[x]==-1){
					cout<<"tribool"<<'\n';
				}else{
					if((k&1) && (col[x]!=col[y])){
						cout<<"tribool"<<'\n';
					}else if(!(k&1) && (col[x]==col[y])){
						cout<<"tribool"<<'\n';
					}else{
						cout<<"expand"<<'\n';
					}
				}
			}
		}
	}
	return 0;
}

本文作者:Kenma

本文链接:https://www.cnblogs.com/Kenma/p/18695913

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Kenma  阅读(4)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起