//最小生成树模板题,用普利姆算法或克鲁斯卡尔算法求解。 #include <bits/stdc++.h> using namespace std; #define int long long const int maxn = (10000+10)*2; const int maxnn = 100+10; struct sy{ int next; int to; int w; } edge[maxn]; int head[maxnn]; int cnt = 0; struct Node{ int number; int len; bool operator < (const Node& n) const { return n.len<len; } } node[maxnn]; int c, n, m; priority_queue<Node> pq; int ans = 0; bool vis[maxn]; void add_edge(int u, int v, int w) { edge[++cnt].next = head[u]; edge[cnt].to = v; edge[cnt].w = w; head[u] = cnt; } void init() { ans = 0; memset(vis, 0, sizeof vis); memset(edge, 0, sizeof edge); memset(head, 0, sizeof head); cnt = 0; } bool prim() { pq.push({1, 0}); while (pq.size()) { int number = pq.top().number; int len = pq.top().len; pq.pop(); // cout<<"number="<<number<<endl; if (vis[number]) continue; // cout<<"len="<<len<<endl; ans += len; vis[number] = true; for (int i=head[number];i;i = edge[i].next) { int next = edge[i].to; int w = edge[i].w; if (vis[next]) continue; pq.push({next, w}); } } for (int i=1;i<=m;i++) { // cout<<"vis[i]="<<vis[i]<<endl; if (!vis[i]) return false; } return true; } signed main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int v1, v2, h; while (cin>>c>>n>>m) { init(); for (int i=1;i<=n;i++) { cin>>v1>>v2>>h; add_edge(v1, v2, h); add_edge(v2, v1, h); } //普利姆算法求最小生成树。 bool flag = prim(); // cout<<"flag="<<flag<<endl; // cout<<"ans="<<ans; if (ans<=c&&flag) cout<<"Yes\n"; else cout<<"No\n"; } return 0; } //克鲁斯卡尔的做法,一定要记得排序 #include <bits/stdc++.h> using namespace std; #define int long long const int maxn = (10000+10)*2; const int maxnn = 100+10; int cnt = 0; int ans = 0; int num = 0; int c, n, m; struct sy{ int u; int v; int w; } edge[maxn]; int fa[maxnn]; int vis[maxnn][maxnn]; pair<int, int> a[maxn]; bool cmp(sy a1, sy a2) { return a1.w<a2.w; } void init() { num = 0; cnt = 0; ans = 0; memset(vis, 0, sizeof vis); for (int i=0;i<maxnn;i++) { fa[i] = i; } } int find(int x) { return x==fa[x]? x:fa[x]=find(fa[x]); } signed main() { int u, v, w; while (cin>>c>>n>>m) { init(); for (int i=1;i<=n;i++) { cin>>u>>v>>w; if (vis[u][v]!=0) vis[u][v] = min(vis[u][v], w); else { vis[u][v] = w; a[++cnt] = make_pair(u, v); } } for (int i=1;i<=cnt;i++) { edge[i].u = a[i].first; edge[i].v = a[i].second; edge[i].w = vis[a[i].first][a[i].second]; } sort(edge + 1, edge + cnt + 1, cmp); //采用克鲁斯卡尔算法去求最小生成树。 //克鲁斯卡尔算法的原理在于不加考虑的加边,但是需要用并查集去检查是否产生回路。 //并查集保存点,每选取一个边去检查两端的点是否在并查集里面是同一个集合。如果是就不加入到结果当中, //遍历每一条边 for (int i=1;i<=cnt;i++) { int u = edge[i].u; int v = edge[i].v; int w = edge[i].w; int rootu = find(u); int rootv = find(v); if (rootu==rootv) continue; ans += w; num++; fa[rootu] = rootv; } // cout<<ans<<" "<<num<<endl; if (ans<=c&&num>=m-1) cout<<"Yes\n"; else cout<<"No\n"; } return 0; }