General meaning
Gives nnThe weight of n nodes, if the weights of two pointsand andThe result of a n d is not0 00 means that there is an edge connection between these two points, and the edge weight islowbit (a & b) lowbit(a \& b)l o w b i t ( a & b ) ask from1 11 go tonnn points, what is the shortest path
analysis
No violence first
Because the points are 1 0 5 10^5105 , the number of all possible edges is1 0 5 ∗ (1 0 5 − 1) / 2 ≈ 1 0 10 10^5 * (10^5-1) / 2 \approx 10^{10}105∗(105−1)/2≈1010
Consider bit operation optimization
We prepare 32 groups, for each value, if this value aaa at positioniii 上有值,即 a & ( 1 < < i ) ≠ 0 a \& (1 << i ) \neq 0 a&(1<<i)=0 means this value is divided into this group, and each value can belong to multiple groups
For each group, we define another variable to represent arrival group iiThe value of the edge weight required by the value in i ttt, t ≥ ( 1 < < i ) t \geq (1 << i) t≥(1<<i)
For starting point 1 11 , we consider every bit of it, if bitiiIf there is a value on i , all other values in the group that reach this position are considered to cost(1 <<i) (1 << i)(1<<i ) . Record the cost of each group, and then perform operations similar to the starting point for each value in each group traversed, similar toBellman − F ord Bellman-FordBellman−F o r d algorithm relaxes until there is no update cost in the entire graph
Finally, consider each bit of the final point, find the least expensive bit and output it
Pay attention to when the starting point and ending point are the same
AC code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// NOLINTNEXTLINE
ll lowBit(ll x) {
return x & (-x); }
void solve() {
ll _;
cin >> _;
for (ll ts = 0; ts < _; ++ts) {
ll n;
cin >> n;
vector<ll> data[40];
vector<ll> cost(40, LONG_LONG_MAX);
vector<ll> a(n);
for (ll i = 0; i < n; ++i) {
cin >> a[i];
for (ll j = 0; j < 40; ++j)
// NOLINTNEXTLINE
if (a[i] & (1ll << j))
data[j].push_back(i);
}
if (n == 1) {
cout << 0 << endl;
continue;
}
queue<ll> q;
for (ll i = 0; i < 40; ++i) {
// NOLINTNEXTLINE
if (a[0] & (1ll << i)) {
q.push(i);
// NOLINTNEXTLINE
cost[i] = 1ll << i;
}
}
while (!q.empty()) {
ll cur = q.front();
q.pop();
for (auto item : data[cur]) {
for (ll i = 0; i < 40; ++i) {
// NOLINTNEXTLINE
if ((a[item] & (1ll << i)) && cost[i] > (1ll << i) + cost[cur]) {
q.push(i);
// NOLINTNEXTLINE
cost[i] = (1ll << i) + cost[cur];
}
}
}
}
ll ans = LONG_LONG_MAX;
for (ll i = 0; i < 40; ++i) {
// NOLINTNEXTLINE
if (a[n - 1] & (1ll << i)) {
ans = min(ans, cost[i]);
}
}
if (ans == LONG_LONG_MAX)
cout << "Impossible" << endl;
else
cout << ans << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
signed localTestCount = 1, localReadPos = cin.tellg();
char localTryReadChar;
do {
if (localTestCount > 20)
throw runtime_error("Check the stdin!!!");
auto startClockForDebug = clock();
solve();
auto endClockForDebug = clock();
cout << "Test " << localTestCount << " successful" << endl;
cerr << "Test " << localTestCount++ << " Run Time: "
<< double(endClockForDebug - startClockForDebug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
} while (localReadPos != cin.tellg() && cin >> localTryReadChar && localTryReadChar != '$' &&
cin.putback(localTryReadChar));
#else
solve();
#endif
return 0;
}