先建一棵最小生成树,然后看有几个连通分量,就建几个机场,最后从已选择的边中,将删除所有比建机场贵的边,加上相应的机场数!
解题思路要清晰
代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int N = 10010; const int M = 100010; int T, A; int n, m, cnt, ans; int cost[M], f[N]; struct edge{ int u, v, w; }e[M]; bool cmp( edge a, edge b ) { return a.w < b.w; } bool cmp1( int a, int b ) { return a > b; } int find( int x ) { return x == f[x] ? x : f[x] = find(f[x]); } void Kru() { for ( int i = 0; i < m; ++i ) { int x = e[i].u, y = e[i].v; int a = find(x), b = find(y); if ( a != b ) { f[a] = b; cost[cnt++] = e[i].w; ans += e[i].w; } } } int main() { int icase = 1; scanf("%d", &T); while ( T-- ) { scanf("%d%d%d", &n, &m, &A); for ( int i = 0; i < m; ++i ) scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w); ans = cnt = 0; for ( int i = 0; i <= n; ++i ) f[i] = i; sort(e, e+m, cmp); Kru(); int num = 0; for ( int i = 1; i <= n; ++i ) if ( i == find(i) ) num++; ans += A*num; sort( cost, cost+cnt, cmp1); for ( int i = 0; i < cnt; ++i ) { if ( cost[i] >= A ) ans = ans + A - cost[i], num++; else break; } printf("Case #%d: %d %d\n", icase++, ans, num); } }