本道题算是最小生成树的变种吧,写的不是非常熟练,特别是并查集,太少写了,所以犯下了很多低级错误

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

不算是很难,实际上,只是把最小生成树的免费部分去掉,再贪心一次就好了