uva11733 Airports
两点之间,要么建飞机场,要么建路,求怎么做花费最小。
最小生成树模板。只不过图不一定连通,做完kruskal后看下有几个连通分量,再用"飞机场"连起来,最后看之前铺的路的花费有没有比修飞机场来的高,如果费用更高,则不修路改为建飞机场。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #define N 10010 #define M 100010 using namespace std; int t,a ,n, m, cnt, ans; int cost[M] ; struct edge{ int u, v, w; }e[M]; struct node{ int fa; }nod[N]; bool cmp( edge a, edge b ) { return a.w < b.w; } bool cmp1( int a, int b ) { return a > b; } void Initial(){ for ( int i = 0; i <= n; ++i ) { nod[i].fa=i; } } int find( int x ) { if(x!=nod[x].fa){ nod[x].fa=find(nod[x].fa); } return nod[x].fa; } void Kruskal() { 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 ) { nod[a].fa = b; cost[cnt++] = e[i].w; ans += e[i].w; } } } int main() { int cased = 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; Initial(); sort(e, e+m, cmp); Kruskal(); int air = 0; for ( int i = 1; i <= n; i++ ){ if ( i == find(i) ) { air++; } } ans += a*air; sort( cost, cost+cnt, cmp1); for ( int i = 0; i < cnt; ++i ) { if ( cost[i] >= a ) { ans = ans + a - cost[i]; air++; } } printf("Case #%d: %d %d\n", cased++, ans, air); } }