题解:P11644 【MX-X8-T3】「TAOI-3」地地爱打卡
前言
诈骗题。
思路分析
首先异或啥的别看了,是假的。
考虑如果要求异或值为 \(x\),如果我们能得到的路径长度为 \(k\),考虑:
-
\(x \le k\),那么可以将 \(k-x\) 的部分分成两半抵消;
-
\(x>k\),那么可以从 \(s\) 出发走到任意一个点再沿反边返回,每次增加 \(2\) 的路径长度。
所以,只需要保证 \(x\) 和 \(k\) 的奇偶性相同就行了。
那么直接做就行了。
-
如果 \(s\) 和 \(t\) 不连通,没戏;
-
如果 \(s\) 和 \(t\) 所在的连通块是二分图,那么看 \(s\) 和 \(t\) 是否同色,判断两点之间路径的奇偶性;
-
如果 \(s\) 和 \(t\) 所在的连通块不是二分图,那么两点之间一定同时存在奇偶路径。
除此之外,还需要特判 \(s=t\) 的情况。
使用并查集和二分图染色实现,总体复杂度 \(O(n\alpha(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;
}

浙公网安备 33010602011771号