造桥与砍树

造桥与砍树

prim算法,堆优化完全图

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve() {
    int n; ll k; cin >> n >> k;
    vector<ll> t(n + 1);
    for(int i = 1; i <= n; i ++) cin >> t[i], t[i] %= k;
    
    if(n == 1) {cout << "0\n"; return;}
    
    set<pair<ll, int>> st;
    for(int i = 1; i <= n; i ++) st.insert({t[i], i});

    priority_queue<tuple<ll, int, int>, vector<tuple<ll, int, int>>, greater<>> pq;

    auto add = [&](int u) {
        if(st.empty()) return;
        auto it = st.lower_bound({k - t[u], -1});
        if(it == st.end()) it = st.begin();
        pq.push({(t[u] + it->first) % k, u, it->second});
    };

    int start = st.begin()->second;
    st.erase(st.begin());
    add(start);

    ll ans = 0;
    while(!pq.empty()) {
        auto [w, x, y] = pq.top(); pq.pop();
        if(!st.count({t[y], y})) continue;
        ans += w;
        st.erase({t[y], y});
        if(st.empty()) break;
        add(x), add(y);
    }
    cout << ans << "\n";
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    int _ = 1; cin >> _;
    while(_--) solve();
    return 0;
}
posted @ 2026-10-11 20:57  thenrify  阅读(6)  评论(0)    收藏  举报