本道题算是最小生成树的变种吧,写的不是非常熟练,特别是并查集,太少写了,所以犯下了很多低级错误
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
class unit {
vector<int> par;
vector<int> ran;
int connect;
public:
unit(int n):par(n+1),ran(n+1),connect(n) {
for(int i = 0;i<n+1;i++) {
par[i] = i;
ran[i] = 0;
}
}
int find(int x) {
if(par[x] == x) {
return x;
}else {
return find(par[x]);
}
}
void unit_all(int x,int y) {
x = find(x);y = find(y);
if(x==y) return;
connect--;
if(ran[x] < ran[y]) {
par[x] = y;
} else {
par[y] = x;
if(ran[x] == ran[y]) ran[x]++;
}
}
inline bool same(int x,int y) {
return find(x)==find(y);
}
bool connected() {
return connect == 1;
}
};
struct edge{int u,v,cost;};
bool cmp(const edge& a,const edge& b) {
return a.cost < b.cost;
}
bool check(ll num,vector<edge>& goal,int n,ll c) {
unit dsu(n);
vector<int> cost;
for(const edge& i:goal) {
if(dsu.connected()) break;
if(!dsu.same(i.u,i.v)) {
if(i.cost > num) {
cost.emplace_back(i.cost);
}
dsu.unit_all(i.u,i.v);
}
}
if(!dsu.connected()) return false;
sort(cost.begin(),cost.end(),greater<int>{});
ll ans = 0;
for(int i = 0;i<cost.size();i++) {
ans += (ll)(i+1)*cost[i];
}
return ans <= c;
}
int main()
{
cin.tie(nullptr)->sync_with_stdio(false);
ll c;int n,m;cin >> n >> m >> c;
vector<edge> nums(m);
for(int i = 0;i<m;i++) {
cin >> nums[i].u >> nums[i].v >> nums[i].cost;
}
sort(nums.begin(),nums.end(),cmp);
ll be = 0;ll en = 1e9+1;
while(be<en) {
ll mid = be+((en-be)>>1);
if(check(mid,nums,n,c)) {
en = mid;
} else {
be = mid+1;
}
}
cout << en;
}
不算是很难,实际上,只是把最小生成树的免费部分去掉,再贪心一次就好了

京公网安备 11010502036488号