hdu 4081 Qin Shi Huang's National Road System(次小生成树prim)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081
题意:有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点。秦始皇希望这所有n-1条路长度之和最短。然后徐福突然有冒出来,说是他有魔法,可以不用人力、财力就变出其中任意一条路出来。
秦始皇希望徐福能把要修的n-1条路中最长的那条变出来,但是徐福希望能把要求的人力数量最多的那条变出来。对于每条路所需要的人力,是指这条路连接的两个城市的人数之和。
最终,秦始皇给出了一个公式,A/B,A是指要徐福用魔法变出的那条路所需人力, B是指除了徐福变出来的那条之外的所有n-2条路径长度之和,选使得A/B值最大的那条。
题解:就是次小生成树稍微改一下就行,这里只能用prim的次小生成树,由于边太多但是点还是1000。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; struct TnT { int x , y , p; }T[1010]; double lowcost[1010] , mmp[1010][1010] , maxpath[1010][1010] , cost[1010]; int pre[1010]; bool vis[1010][1010] , has[1010]; double prim( int n) { lowcost[1] = 0; pre[1] = 0; memset (vis , false , sizeof (vis)); memset (has , false , sizeof (has)); has[1] = true ; for ( int i = 2 ; i <= n ; i++) { lowcost[i] = mmp[1][i]; pre[i] = 1; } double sum = 0; for ( int i = 2 ; i <= n ; i++) { int pos = 0; double MIN = 10000000000000.0; for ( int j = 1 ; j <= n ; j++) { if (!has[j] && lowcost[j] < MIN) { MIN = lowcost[j]; pos = j; } } sum += MIN; vis[pos][pre[pos]] = vis[pre[pos]][pos] = true ; has[pos] = true ; for ( int j = 1 ; j <= n ; j++) { if (has[j] && j != pos) { maxpath[pos][j] = maxpath[j][pos] = max(maxpath[j][pre[pos]] , lowcost[pos]); } if (!has[j]) { if (mmp[pos][j] < lowcost[j]) { lowcost[j] = mmp[pos][j]; pre[j] = pos; } } } } return sum; } double getlen( int a , int b) { return sqrt ((T[a].x - T[b].x) * (T[a].x - T[b].x) + (T[a].y - T[b].y) * (T[a].y - T[b].y)); } int main() { int t; scanf ( "%d" , &t); while (t--) { int n; scanf ( "%d" , &n); for ( int i = 1 ; i <= n ; i++) { int u , v , p; scanf ( "%d%d%d" , &u , &v , &p); T[i].x = u , T[i].y = v , T[i].p = p; cost[i] = 1.0 * p; } for ( int i = 1 ; i <= n ; i++) { for ( int j = 1 ; j <= n ; j++) { mmp[i][j] = getlen(i , j); } } double sum = prim(n); double val = 0.0; for ( int i = 1 ; i <= n ; i++) { for ( int j = 1 ; j <= n ; j++) { if (i == j) continue ; if (!vis[i][j]) { val = max(val , 1.0 * (cost[i] + cost[j]) / (sum - maxpath[i][j])); } else { val = max(val , 1.0 * (cost[i] + cost[j]) / (sum - mmp[i][j])); } } } printf ( "%.2lf\n" , val); } return 0; } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步