造桥与砍树
造桥与砍树
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;
}

浙公网安备 33010602011771号