https://vjudge.net/problem/HDU-4081
题意:
秦始皇想要修长城,修成生成树的样子,这是一个大师出现了,他说他可以不耗费人力修出一条路来。他们的目的很不一样,神特么有分歧,最后他们达成了一个协议,假设一个城市的人口为a。那么最后不耗费人力修的那条路所相连的两个城市的人口之和A与修路花费的人力B之比 A/B最大,并且输出最大值。
思路:
枚举去掉每一条边。
首先求出最小生成树,对于最小生成树中的每一条边,如果这条边不花费人力,那么直接计算A和B就可以了。
那么问题是如果选择的边不在最小生成树中的话,应该怎么办。为了形成生成树,肯定要将最小生成树生成树中的边去掉,又为了保持边的权值之和是最小的,所以自然想到了次小生成树,用到了maxn[u][v]那个数组,所以就将maxn[u][v]减去进行比较就行了。maxn[u][v]的求法请见次小生成树学习的博文。
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #include <math.h> 5 #include <vector> 6 #include <queue> 7 using namespace std; 8 9 struct node 10 { 11 int x,y; 12 double len; 13 } a[1000005]; 14 15 struct com 16 { 17 int id; 18 double dis; 19 }; 20 21 int h[1005],z[1005],p[1005]; 22 int par[1005]; 23 bool v[1000005]; 24 double ma[1005][1005]; 25 bool vis[1005]; 26 vector<node> no[1005]; 27 28 bool cmp(node aa,node bb) 29 { 30 if (aa.len == bb.len) 31 { 32 double t1 = p[aa.x] + p[aa.y]; 33 double t2 = p[bb.x] + p[bb.y]; 34 35 return t2 < t1; 36 } 37 38 return aa.len < bb.len; 39 } 40 41 void init(int n) 42 { 43 for (int i = 0;i < n;i++) 44 par[i] = i; 45 } 46 47 int fin(int x) 48 { 49 if (x == par[x]) return x; 50 else return par[x] = fin(par[x]); 51 } 52 53 void unit(int x,int y) 54 { 55 x = fin(x); 56 y = fin(y); 57 58 if (x != y) par[x] = y; 59 } 60 61 double cal(int i,int j) 62 { 63 double dis1 = 1.0 * (h[i] - h[j]) * (h[i] - h[j]); 64 double dis2 = 1.0 * (z[i] - z[j]) * (z[i] - z[j]); 65 66 return sqrt(dis1 + dis2); 67 } 68 69 void adde(int x,int y,double dis) 70 { 71 node t; 72 73 t.x = x; 74 t.y = y; 75 t.len = dis; 76 77 no[x].push_back(t); 78 } 79 80 void bfs(int k) 81 { 82 memset(vis,0,sizeof(vis)); 83 84 com now,nex; 85 86 queue<com> qq; 87 88 while (!qq.empty()) qq.pop(); 89 90 now.id = k;now.dis = 0; 91 vis[now.id] = 1; 92 93 qq.push(now); 94 95 while (!qq.empty()) 96 { 97 com tc = qq.front();qq.pop(); 98 99 int tx = tc.id; 100 double maxn = tc.dis; 101 102 for (int i = 0;i < no[tx].size();i++) 103 { 104 node tmp = no[tx][i]; 105 int ty = tmp.y; 106 double tmaxn = tmp.len; 107 108 if (!vis[ty]) 109 { 110 vis[ty] = 1; 111 nex.id = ty; 112 nex.dis = tmaxn; 113 114 if (maxn > tmaxn) nex.dis = maxn; 115 116 ma[k][ty] = nex.dis; 117 118 qq.push(nex); 119 } 120 } 121 } 122 } 123 124 int main() 125 { 126 int t; 127 128 scanf("%d",&t); 129 130 while (t--) 131 { 132 int n; 133 134 scanf("%d",&n); 135 136 init(n); 137 memset(a,0,sizeof(a)); 138 memset(v,0,sizeof(v)); 139 memset(no,0,sizeof(no)); 140 141 for (int i = 0;i < n;i++) 142 { 143 scanf("%d%d%d",&h[i],&z[i],&p[i]); 144 } 145 146 int cnt = 0; 147 148 for (int i = 0;i < n;i++) 149 for (int j = i + 1;j < n;j++) 150 { 151 a[cnt].x = i;a[cnt].y = j; 152 a[cnt].len = cal(i,j); 153 cnt++; 154 } 155 156 double es = 0; 157 158 sort(a,a+cnt,cmp); 159 160 for (int i = 0;i < cnt;i++) 161 { 162 int x = a[i].x,y = a[i].y; 163 164 if (fin(x) == fin(y)) continue; 165 166 unit(x,y); 167 168 v[i] = 1; 169 170 adde(x,y,a[i].len); 171 adde(y,x,a[i].len); 172 173 es += a[i].len; 174 } 175 176 double maxn = 0; 177 178 for (int i = 1;i <= n;i++) 179 { 180 bfs(i); 181 } 182 183 for (int i = 0;i < cnt;i++) 184 { 185 if (v[i]) 186 { 187 double ns = 0; 188 int x = a[i].x,y = a[i].y; 189 190 ns += p[x];ns += p[y]; 191 192 es -= a[i].len; 193 194 if (ns / es > maxn) maxn = ns / es; 195 196 es += a[i].len; 197 } 198 else 199 { 200 double ns = 0; 201 int x = a[i].x,y = a[i].y; 202 203 ns += p[x];ns += p[y]; 204 205 es -= ma[x][y]; 206 207 if (ns / es > maxn) maxn = ns / es; 208 209 es += ma[x][y]; 210 } 211 } 212 213 printf("%.2f ",maxn); 214 } 215 216 return 0; 217 }