前言
诈骗题。
思路分析
首先异或啥的别看了,是假的。
考虑如果要求异或值为 \(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;
}