博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uvalive 5731 Qin Shi Huang’s National Road System
阅读量:4629 次
发布时间:2019-06-09

本文共 4274 字,大约阅读时间需要 14 分钟。

题意:

秦始皇要修路使得所有的城市连起来,并且花费最少;有一个人,叫徐福,他可以修一条魔法路,不花费任何的钱与劳动力。

秦始皇想让修路的费用最少,但是徐福想要受益的人最多,所以他们经过协商,决定让 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 
2 #include
3 #include
4 #include
5 #include
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 else144 {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 }

 

转载于:https://www.cnblogs.com/kickit/p/8809028.html

你可能感兴趣的文章
zabbix 监控tomcat实例
查看>>
WinForm 实现验证码
查看>>
[C++]C++中的IO类
查看>>
笔记本电脑(Windows7)实现无线AP
查看>>
JqGridView 1.0.0.0发布
查看>>
欲精一行,必先通十行
查看>>
前端相关html和css
查看>>
celery
查看>>
实现音乐播放器
查看>>
BZOJ1002 [FJOI2007]轮状病毒(最小生成树计数)
查看>>
uv_timer_t的释放问题
查看>>
【bzoj1853】[Scoi2010]幸运数字 容斥原理+搜索
查看>>
【bzoj2770】YY的Treap 权值线段树
查看>>
利用闭包实现多次ajax请求只执行最后一次
查看>>
BZOJ1702: [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列
查看>>
Shell基础命令之echo
查看>>
windows 常用命令
查看>>
python中tornado的第一个例子
查看>>
分享下自己写的一个微信小程序请求远程数据加载到页面的代码
查看>>
微软技术的变迁
查看>>