题意,给出n个点,m条边.定义mex(wi,wi&wi+1,wi&wi+1&wi+2)为从u,到v的边权,给出q个查询,给出两个点之间的边权。
容易发现012只可能同时存在两个,所以答案只在这三个数之间,
因为如果存在1,就说明最后一位一定为1,就不可能通过与得到一个偶数,只能得到0
如果存在2,那么最后一位一定为0,就不可能得到奇数,只能得到0.
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
struct t {
int u, v, w;
}edge[maxn * 2];
int fa[maxn][30];
int find(int x, int id)
{
if (fa[x][id] == -1) return x;
return fa[x][id] == x ? x : fa[x][id] = find(fa[x][id], id);
}
int can[30][maxn];//考虑第i位时的某个点在与得到1之前是否存在经过一条偶数边
int main()
{
int n, m;
std::ios::sync_with_stdio(0);
cin >> n >> m;
for (int i = 1; i <= m; ++i)
cin >> edge[i].u >> edge[i].v >> edge[i].w;
for (int i = 0; i <= 29; ++i)
for (int j = 1; j <= n; ++j)
fa[j][i] = -1;
for (int i = 0; i <= 29; ++i) {
for (int j = 1; j <= m; ++j)
{
if ((edge[j].w >> i) & 1)
{
int fx = find(edge[j].u, i);
int fy = find(edge[j].v, i);
if (fx != fy)
fa[fy][i] = fx;
}
}//这样为什么能说明是在奇数与的时候得不到1,是因为当前图在只考虑第i位时得到的连通分量
//如果某两个点联通就说明在第i位来考虑,当前相与一定得不到1,因为第i位都是1
if (i > 0) {
for (int j = 1; j <= m; ++j)
if (edge[j].w % 2 == 0) {
int fx = find(edge[j].u, i);
int fy = find(edge[j].v, i);
can[i][fx] = 1;
can[i][fy] = 1;
}
}
}
int q;
cin >> q;
for (int i = 1; i <= q; ++i) {
int u, v;
cin >> u >> v;
int ans = 2;
for (int j = 0; j <= 29; ++j) {
if (find(u, j) == find(v, j))
{
ans = 0;
break;
}
}//这已经说明路径之中存在0
//所以只用后面不存在1即可
//不是最低位不存在1,而是在考虑
// 都是奇数边-》一条偶数边-》随便走
//我只需要考虑所经过的奇数边进行与之后得不到1,就遇到一个偶数边,关闭最低位的情况即可
if (ans != 0) {
for (int i = 1; i <= 29; ++i)
if (can[i][find(u, i)])
ans = 1;
}
cout << ans << '\n';
}
return 0;
}