【Niu Ke】Niu Ke Practice Tournament 67-E-Niu Mei travels to the city-bit calculation optimization

Topic link

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(1051)/21010

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-FordBellmanF 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;
}

Guess you like

Origin blog.csdn.net/m0_43448982/article/details/108012873