E - AND-MEX Walk
分析:
-
结论+并查集的连通性求解
-
首先易证答案就3种:0,1,2
故分类讨论(分别对30位求解连通性):
- 0:存在某一位使得u,v连通
- 1:存在某一位的连通块的 边的集合 存在偶数边,这样就能先到 偶数边 再到v 这样保证 ans=1
- 2:其余情况
#include <bits/stdc++.h>
#define int long long
#define Pa pair<int,int>
using namespace std;
const int N=2e5+5;
vector <pair<int,int> > g[N+5];
int f[32][N];
int fd(int x,int k){ return f[x][k]==k ? k : f[x][k]=fd(x,f[x][k]); }
int vis[N];
void solve()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
g[u].push_back({v,w});
g[v].push_back({u,w}) ;
}
for(int i=0;i<30;i++) for(int j=1;j<=n;j++) f[i][j]=j;
for(int i=0;i<30;i++)
{
for(int j=1;j<=n;j++)
{
int x=fd(i,f[i][j]);
for(auto it : g[j])
{
int v=it.first, w=it.second;
if((w>>i)&1)
{
int y=fd(i,f[i][v]);
if(x!=y) f[i][y]=x;
}
}
}
}
vector <int> e;
for(int i=1;i<=n;i++)
{
for(auto it : g[i])
{
int v=it.first, w=it.second;
if(w%2==0)
{
if(!vis[i]) e.push_back(i);
if(!vis[v]) e.push_back(v);
vis[i]=vis[v]=1;
}
}
}
for(int i=1;i<30;i++)
{
vector <int> tp(n+5);
for(int x : e) tp[fd(i,f[i][x])]=1;
for(int j=1;j<=n;j++) vis[j]|=tp[fd(i,f[i][j])];
}
int q; cin>>q;
while(q--)
{
int u,v;
scanf("%lld%lld",&u,&v);
int fg=0;
for(int i=0;i<30;i++)
{
int x=fd(i,f[i][u]), y=fd(i,f[i][v]);
if(x==y) {fg=1; break;}
}
if(fg) cout<<"0\n";
else if(vis[u] ) cout<<"1\n";
else cout<<"2\n";
}
}
signed main()
{
int T=1;
//cin>>T;
while(T--) solve();
}