B 异或图
题目地址:
基本思路:
这题的数据范围比较大有点卡常 #define int long long 成功让我T了五次,我以后再也不偷懒了QAQ;
这题我们稍做观察可以就可以发现,,两个位置要能联通,那么要么是就是,这时一步就能到达;
要么必须是这时如果我们有一个中间位置,这个位置和或的异或是,就也能到达,这时的最短路长是2;
除了这两种情况之外,根据异或运算的性质和举例尝试我们能发现不会再有其他情况可以到达了。
所以每次对以上情况进行判断就是了。
参考代码:
#pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; #define IO std::ios::sync_with_stdio(false) #define ll long long #define rep(i, l, r) for (int i = l; i <= r; i++) #define per(i, l, r) for (int i = l; i >= r; i--) #define mset(s, _) memset(s, _, sizeof(s)) #define pb push_back #define pii pair <int, int> #define mp(a, b) make_pair(a, b) #define INF (int)1e18 inline int read() { int x = 0, neg = 1; char op = getchar(); while (!isdigit(op)) { if (op == '-') neg = -1; op = getchar(); } while (isdigit(op)) { x = 10 * x + op - '0'; op = getchar(); } return neg * x; } inline void print(int x) { if (x < 0) { putchar('-'); x = -x; } if (x >= 10) print(x / 10); putchar(x % 10 + '0'); } const int maxn = 1e6 + 50000; int n,q,w[maxn],memo[maxn]; signed main() { n = read(),q = read(); mset(memo,0); rep(i, 1, n) w[i] = read(),memo[w[i]] = 1; while (q--) { int k = read() , x = read() , y = read(); if ((w[x] ^ w[y]) == k) {//w[x]^w[y]就是k的情况; print(1); puts(""); continue; } if (w[x] != w[y]) { //这时一定不能联通; print(-1); puts(""); continue; } int tmp = (w[x] ^ k); if (memo[tmp]) { //能找到需要的中间值; print(2); }else print(-1); puts(""); } return 0; }