1. 程式人生 > >uvalive 5731 Qin Shi Huang’s National Road System

uvalive 5731 Qin Shi Huang’s National Road System

枚舉 size algorithm style stdio.h lse max const set

題意:

秦始皇要修路使得所有的城市連起來,並且花費最少;有一個人,叫徐福,他可以修一條魔法路,不花費任何的錢與勞動力。

秦始皇想讓修路的費用最少,但是徐福想要受益的人最多,所以他們經過協商,決定讓 A / B 最大,A代表被魔法路連接的兩個城市的人口總數,B代表修的路中非魔法路的總長度。

輸出 A / B 的最大值。

思路:

A / B 最大,則A盡可能大,B盡可能小,所以首先把MST求出來。由於每個城市的人口有很大的偏差,所以必須枚舉每一條邊,計算連接的兩個城市的人口,復雜度為O(n^2),所以每次替換邊的復雜度必須是O(1)。

由於是稠密圖,所以用prim算法,prim算法在O(n^2)的復雜度的時候,可以維護最小生成樹上兩點之間的最長邊,這樣就可以在過程中把兩點間的最長邊保存下來。這個是依靠已知的前驅節點實現的。復雜度為O(n^2)。

枚舉每一條邊時,如果這條邊是MST中的邊,那麽就直接計算 A / B;如果這條邊不在MST中,加入這條邊就會成環,這時我們保存的信息就起作用了,成環之後把在MST中的連接這兩點的最長邊去掉,就是新的生成樹的權值,且保證了B盡可能小。替換的時間復雜度為O(1)。

代碼:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <math.h>
  6 using namespace
std; 7 const int maxn = 1005; 8 double path[maxn][maxn]; 9 double g[maxn][maxn]; 10 double dis[maxn]; 11 bool vis[maxn]; 12 bool used[maxn][maxn]; 13 int peo[maxn]; 14 int pre[maxn]; 15 double ans; 16 struct point 17 { 18 int x,y; 19 }p[maxn]; 20 21 double cal(int i,int j) 22 {
23 double x2 = (p[i].x - p[j].x) * (p[i].x - p[j].x); 24 double y2 = (p[i].y - p[j].y) * (p[i].y - p[j].y); 25 26 return sqrt(x2 + y2); 27 } 28 29 int prim(int n) 30 { 31 memset(vis,0,sizeof(vis)); 32 memset(path,0,sizeof(path)); 33 memset(used,0,sizeof(used)); 34 for (int i = 0;i <= n;i++) dis[i] = 1e15; 35 36 vis[1] = 1; 37 dis[1] = 0; 38 39 int tot = 0; 40 ans = 0; 41 //double len = 0; 42 43 for (int i = 2;i <= n;i++) 44 { 45 pre[i] = 1; 46 dis[i] = g[1][i]; 47 } 48 49 for (int i = 1;i < n;i++) 50 { 51 int u; 52 double d = 1e15; 53 54 for (int j = 1;j <= n;j++) 55 { 56 if (!vis[j] && dis[j] < d) 57 { 58 d = dis[j]; 59 u = j; 60 } 61 } 62 63 vis[u] = 1; 64 65 ans += d; 66 67 //tot = max(peo[u] + peo[pre[u]],tot); 68 69 used[u][pre[u]] = used[pre[u]][u] = 1; 70 71 for (int j = 1;j <= n;j++) 72 { 73 if (vis[j] && j != u) 74 path[u][j] = path[j][u] = max(d,path[j][pre[u]]); 75 } 76 77 for (int j = 1;j <= n;j++) 78 { 79 if (!vis[j]) 80 { 81 if (g[u][j] < dis[j]) 82 { 83 dis[j] = g[u][j]; 84 pre[j] = u; 85 } 86 } 87 } 88 } 89 90 //printf("%.2f **\n",ans); 91 92 return tot; 93 } 94 95 int main() 96 { 97 int t; 98 99 scanf("%d",&t); 100 101 while (t--) 102 { 103 int n; 104 105 scanf("%d",&n); 106 107 for (int i = 1;i <= n;i++) 108 { 109 scanf("%d%d%d",&p[i].x,&p[i].y,&peo[i]); 110 } 111 112 for (int i = 1;i <= n;i++) 113 { 114 for (int j = 1;j <= n;j++) 115 { 116 g[i][j] = 1e15; 117 } 118 } 119 120 for (int i = 1;i <= n;i++) 121 { 122 for (int j = i+1;j <= n;j++) 123 { 124 g[i][j] = g[j][i] = cal(i,j); 125 } 126 } 127 128 prim(n); 129 130 double ans1 = 0; 131 132 for (int i = 1;i <= n;i++) 133 { 134 for (int j = i + 1;j <= n;j++) 135 { 136 if (used[i][j]) 137 { 138 int peop = peo[i] + peo[j]; 139 ans1 = max(peop / (ans - g[i][j]),ans1); 140 141 //printf("%d %d %d %.2f **\n",i,j,peop,ans - g[i][j]); 142 } 143 else 144 { 145 int peop = peo[i] + peo[j]; 146 ans1 = max(peop / (ans - path[i][j]),ans1); 147 //printf("%d %d %d %.2f **\n",i,j,peop,ans - path[i][j]); 148 } 149 } 150 } 151 152 printf("%.2f\n",ans1); 153 154 //printf("%.2f",path[1][4]); 155 } 156 157 return 0; 158 }

uvalive 5731 Qin Shi Huang’s National Road System