CF1659E AND-MEX Walk 题解
jiangtaizhe001 · · 题解
可能更好的阅读体验
题目传送门
题目大意
给定一个无向带权图,总共有
数据范围:
题目解析
设路径上的
首先我们通过样例发现一个结论:答案只可能是
其实就是证明答案不是
我们发现序列
如果答案不是
这样我们只需要判断答案是否为
答案为
然后就是答案为
不难发现答案为
换句话说,只要在走这一条边之前的与和大于
那么怎么得到这样一条路径呢?
显然我们需要选定一位
具体用代码实现的话需要利用前面建立的并查集,并且记录每一个点所有的出边的边权的与和
如果答案不是
代码:
#include<cstdio>
#define gc getchar
#define maxn 100039
using namespace std;
int read(){
char c=gc(); int s=0; int flag=0;
while((c<'0'||c>'9')&&c!='-') c=gc(); if(c=='-') c=gc(),flag=1;
while('0'<=c&&c<='9'){ s=(s<<1)+(s<<3)+(c^48); c=gc(); }
if(flag) return -s; return s;
}
int n,m,u,v,w,T,fa[30][maxn],f[maxn],s[maxn],flag[maxn];
int getfa(int x,int y){ if(fa[x][y]==y) return y; else return fa[x][y]=getfa(x,fa[x][y]); }
int check0(){ int i; for(i=0;i<30;i++) if(getfa(i,u)==getfa(i,v)) return 1; return 0; }
int main(){
n=read(); m=read(); int i,j,k; for(i=0;i<30;i++) for(j=1;j<=n;j++) fa[i][j]=j;
for(i=1;i<=n;i++) f[i]=(1<<30)-1;
for(i=1;i<=m;i++){
u=read(); v=read(); w=read(); f[u]&=w; f[v]&=w;
for(j=0;j<30;j++) if(w&(1<<j)) fa[j][getfa(j,u)]=getfa(j,v);
}
for(k=1;k<30;k++){
for(i=1;i<=n;i++) s[i]=(1<<30)-1;
for(i=1;i<=n;i++) s[getfa(k,i)]&=f[i];
for(i=1;i<=n;i++) if(s[getfa(k,i)]==0) flag[i]=1;
} T=read(); while(T--){
u=read(); v=read(); if(check0()) puts("0"); else if(flag[u]) puts("1"); else puts("2");
} return 0;
}