uva 1494(MST+LCA)
题意:有n个点告诉你每个点坐标和他上面的权值,任意两个点之间都有边权值是他们的距离,现在能免去花费一条边,定义a为这条边两个结点权值之和,b连通其余节点的最小花费,现在求a/b的最大值。
思路:先求最小生成树,然后枚举每条变,若加上边会成环则删除环上除去这条边的权值最大的边。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last modified : 2014-02-08 13:40 5 * Filename : uva_1494.cpp 6 * Description : 7 * ************************************************/ 8 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <cmath> 14 #include <algorithm> 15 #include <queue> 16 #include <stack> 17 #include <vector> 18 #include <set> 19 #include <map> 20 #define MP(a, b) make_pair(a, b) 21 #define PB(a) push_back(a) 22 23 using namespace std; 24 typedef long long ll; 25 typedef pair<int, int> pii; 26 typedef pair<unsigned int,unsigned int> puu; 27 typedef pair<int, double> pid; 28 typedef pair<ll, int> pli; 29 typedef pair<int, ll> pil; 30 31 const int INF = 0x3f3f3f3f; 32 const double eps = 1E-6; 33 const int LEN = 1010; 34 const int LOGLEN = 22; 35 vector<pid> Map[LEN]; 36 int n, m, top, fa[LEN], dep[LEN], parent[LOGLEN][LEN], tag[LEN*LEN]; 37 double rd[LOGLEN][LEN]; 38 struct V{double x, y, val;}; 39 struct E{ 40 int u, v; 41 double val; 42 }; 43 E edge[LEN*LEN]; 44 V vv[LEN]; 45 46 double dis(int a, int b){ 47 return sqrt((vv[a].x-vv[b].x)*(vv[a].x-vv[b].x) + (vv[a].y-vv[b].y)*(vv[a].y-vv[b].y)); 48 } 49 bool cmp(E a, E b){ return a.val < b.val;} 50 //UFSet 51 void init(){for(int i=0; i<LEN; i++) {fa[i] = i;Map[i].clear();}} 52 int Find(int x){return fa[x] == x? x: fa[x] = Find(fa[x]);} 53 //MST 54 double kruskal(){ 55 int cnt = 0; 56 double ret = 0; 57 sort(edge, edge+top, cmp); 58 for(int i=0; i<top; i++){ 59 int pa = Find(edge[i].u), pb = Find(edge[i].v); 60 if(pa == pb) continue; 61 fa[pa] = pb; 62 tag[i] = 1; 63 Map[edge[i].u].PB(MP(edge[i].v, edge[i].val)); 64 Map[edge[i].v].PB(MP(edge[i].u, edge[i].val)); 65 cnt++; ret+=edge[i].val; 66 if(cnt == n-1) break; 67 } 68 return ret; 69 } 70 //LCA 71 void dfs(int v, int fa, int d){ 72 parent[0][v] = fa; 73 rd[0][v] = -1; 74 dep[v] = d; 75 for(int i=0; i<Map[v].size(); i++){ 76 int x = Map[v][i].first; 77 double y = Map[v][i].second; 78 if(x != fa)dfs(x, v, d+1); 79 else rd[0][v] = y; 80 } 81 } 82 83 void initLCA(int root){ 84 memset(rd, 0, sizeof rd); 85 dfs(root, -1, 0); 86 for(int i=0; i<LOGLEN-1; i++) 87 for(int j=0; j<n; j++){ 88 if(parent[i][j]<0) rd[i+1][j] = parent[i+1][j] = -1; 89 else{ 90 parent[i+1][j] = parent[i][parent[i][j]]; 91 rd[i+1][j] = max(rd[i][parent[i][j]], rd[i][j]); 92 } 93 } 94 } 95 96 double LCA(int u, int v){ 97 if(dep[u] > dep[v]) swap(u, v); 98 double ret = 0; 99 for(int i=0; i<LOGLEN; i++) 100 if(((dep[v] - dep[u]) >> i) & 1){ 101 ret = max(ret, rd[i][v]); 102 v = parent[i][v]; 103 } 104 if(u == v) return ret; 105 for(int i=LOGLEN-1; i>=0; i--) 106 if(parent[i][u] != parent[i][v]){ 107 ret = max(ret, rd[i][u]); 108 ret = max(ret, rd[i][v]); 109 u = parent[i][u]; 110 v = parent[i][v]; 111 } 112 ret = max(ret, rd[0][u]); 113 ret = max(ret, rd[0][v]); 114 return ret; 115 } 116 117 int main() 118 { 119 // freopen("in.txt", "r", stdin); 120 121 int T; 122 scanf("%d", &T); 123 while(T--){ 124 scanf("%d", &n); 125 for(int i=0; i<n; i++) 126 scanf("%lf%lf%lf", &vv[i].x, &vv[i].y, &vv[i].val); 127 top = 0;memset(tag, 0, sizeof tag); 128 for(int i=0; i<n; i++) 129 for(int j=i+1; j<n; j++){ 130 edge[top].u = i; 131 edge[top].v = j; 132 edge[top++].val = dis(i, j); 133 } 134 init(); 135 double aval = kruskal(), ans = 0; 136 initLCA(0); 137 for(int i=0; i<top; i++){ 138 int a = edge[i].u, b = edge[i].v; 139 double tl = LCA(a, b), A = vv[a].val+vv[b].val, B; 140 if(tag[i]) B = aval-edge[i].val; 141 else B = aval - tl; 142 ans = max(ans, A/B); 143 } 144 printf("%.2lf\n", ans); 145 } 146 return 0; 147 }
奔跑吧!少年!趁着你还年轻