uva 1494(MST+LCA)

题意:有n个点告诉你每个点坐标和他上面的权值,任意两个点之间都有边权值是他们的距离,现在能免去花费一条边,定义a为这条边两个结点权值之和,b连通其余节点的最小花费,现在求a/b的最大值。

思路:先求最小生成树,然后枚举每条变,若加上边会成环则删除环上除去这条边的权值最大的边。

代码如下:

  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 }
View Code

 

posted @ 2014-02-08 17:33  张小豪  阅读(422)  评论(0编辑  收藏  举报