思路

最小生成树板子题,用Kruskal硬过就行了。
算法流程:
初始设点在集合A,无连边;
将图中的边按照权值从小到大排序,然后从最小的边开始连接(使用并查集);
将边的两端点加入集合B,如果当前边的两个端点不都在集合A,则进行连接;
选择m-1条边的时候刚好将m个点连上,此时判断权值之和是否大于c。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=10005,maxm=100005;

struct E{
    int from,next,to,dis;
}edge[maxm*2];

int c,n,m,u,v,w;
int head[maxn],cnt=0,fa[maxn];

int find(int x){
    if(fa[x]==x) return x;
    else return fa[x]=find(fa[x]);
}

void unite(int x,int y){
    fa[find(x)]=find(y);
}

void addedge(int from,int to,int dis){
    edge[++cnt].next=head[from];
    edge[cnt].from=from;
    edge[cnt].to=to;
    edge[cnt].dis=dis;
    head[from]=cnt;
}

bool cmp(E a,E b){
    return a.dis<b.dis;
}

int main(){
    scanf("%d%d%d",&c,&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    int tot=0,sm=0;
    for(int i=1;i<=m;i++) fa[i]=i;
    sort(edge+1,edge+1+cnt,cmp);
    for(int i=1;i<=cnt;i++){
        if(find(edge[i].to)!=find(edge[i].from)){
            sm+=edge[i].dis;
            unite(edge[i].to,edge[i].from);
            tot++;
        }
        if(tot==m-1) break;
    }
    if(sm<=c) cout<<"Yes"<<endl;
    else cout<<"No"<<endl;
    return 0;
}