UVA 1494 Qin Shi Huang's National Road System ( 次小生成樹 )
UVa Online Judge
很明顯是一個類似次小生成樹的問題,因為只刪除一個邊,我們考慮一一枚舉要刪除的邊互相比較。將每個點對的最小瓶頸路徑預處理 O( n * n ),檢查刪除後的權值總和就能達到 O( 1 )。總複雜度 O( m lg m + n * n )。關於最小瓶頸路徑可以看這則
生成樹相關問題 -- 訓練指南 - 0w1
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e3 + 3; int n, m; int x[MAXN], y[MAXN], p[MAXN]; struct Edge{ int u, v; double c; bool operator < (const Edge &oth) const{ return c < oth.c; } } es[MAXN * MAXN]; vector<Edge> G[MAXN]; int head[MAXN]; int find(int x){ return x == head[x] ? x : head[x] = find( head[x] ); } bool unite(int a, int b){ int x = find( a ), y = find( b ); if( x == y ) return false; head[ x ] = y; return true; } double euDis(int a, int b){ double x2 = ( x[ a ] - x[ b ] ) * ( x[ a ] - x[ b ] ); double y2 = ( y[ a ] - y[ b ] ) * ( y[ a ] - y[ b ] ); return sqrt( x2 + y2 ); } double kruskal(){ m = 0; for(int i = 0; i < n; ++i) for(int j = i + 1; j < n; ++j) es[ m++ ] = (Edge){ i, j, euDis( i, j ) }; sort( es, es + m ); for(int i = 0; i < n; ++i) head[i] = i, G[i].clear(); double ans = 0.0; int edge_cnt = 0; for(int i = 0; i < m; ++i){ int u = es[i].u, v = es[i].v; double c = es[i].c; if( unite( u, v ) ){ G[u].push_back( (Edge){ u, v, c } ); G[v].push_back( (Edge){ v, u, c } ); ans += c; if( ++edge_cnt == n - 1 ) break; } } return ans; } double maxcost[MAXN][MAXN]; // maximum cost in route between u <-> v vector<int> visited; void dfs(int v, int u, double wuv){ // from u, now on v, cost of u <-> v is wuv for(int x: visited) maxcost[x][v] = maxcost[v][x] = max( maxcost[x][u], wuv ); visited.push_back( v ); for(int i = 0; i < G[v].size(); ++i){ int nv = G[v][i].v; if( nv == u ) continue; dfs( nv, v, G[v][i].c ); } } void findBottleneckPath(){ memset( maxcost, 0, sizeof(maxcost) ); visited.clear(); dfs( 0, -1, 0.0 ); } void solve(){ double mstv = kruskal(); findBottleneckPath(); double ans = -1; for(int i = 0; i < n; ++i) for(int j = i + 1; j < n; ++j) ans = max( ans, ( p[i] + p[j] ) / ( mstv - maxcost[i][j] ) ); printf("%.2lf\n", ans); } int main(){ int T; scanf("%d", &T); while( T-- ){ scanf("%d", &n); for(int i = 0; i < n; ++i) scanf("%d%d%d", &x[i], &y[i], &p[i]); solve(); } return 0; }