hdu4081(次小生成树) Qin Shi Huang's National Road System
2016-03-25 13:41
369 查看
下面让我们来分析一下这个题
秦始皇统一中国之后要在全国修公路连接各个城市,抠门皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/(生成树长度-这条路的长度))的路让他变,求这个比值最大值。
先说说次小生成树的形成过程,在prim最小生成树的算法基础上,记录每两个点之间路径上最长的边长,如果要求次小生成树的数值的话,遍历每一条不在最小生成树中的边,用来替换一条这两个点在最小生成树上那条路径的最长的边,记录当前生成树的总长度,遍历一圈找最小的。
这个题没问次小生成树的值,但是用到了路径最长边这个数组,我叫他Max[][],题中问的是(两个城市人口/(生成树长度-这条路的长度)),我们首先考虑分母最小,因为对于某个边来说分子是定值啊,分母分成两种情况:1.该边就在最小生成树里,则直接减掉。2.该边在最小生成树外,那么减掉的是构成的环里面除了这条边以外的最大的边
秦始皇统一中国之后要在全国修公路连接各个城市,抠门皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城市人口/(生成树长度-这条路的长度))的路让他变,求这个比值最大值。
先说说次小生成树的形成过程,在prim最小生成树的算法基础上,记录每两个点之间路径上最长的边长,如果要求次小生成树的数值的话,遍历每一条不在最小生成树中的边,用来替换一条这两个点在最小生成树上那条路径的最长的边,记录当前生成树的总长度,遍历一圈找最小的。
这个题没问次小生成树的值,但是用到了路径最长边这个数组,我叫他Max[][],题中问的是(两个城市人口/(生成树长度-这条路的长度)),我们首先考虑分母最小,因为对于某个边来说分子是定值啊,分母分成两种情况:1.该边就在最小生成树里,则直接减掉。2.该边在最小生成树外,那么减掉的是构成的环里面除了这条边以外的最大的边
#include <iostream> #include <math.h> #include <string.h> #include <stdio.h> using namespace std; const int MAXN=1005; const int INF=0x3f3f3f3f; bool vis[MAXN]; double lowc[MAXN]; int pre[MAXN]; double Max[MAXN][MAXN]; bool used[MAXN][MAXN]; double cost [MAXN][MAXN]; struct sa { int x,y,p; } num[1005]; double Dis(sa a,sa b) { return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y)); } /*double max(double m1,double m2) { if(m1>m2) return m1; return m2; }*/ double prim(int n)//第一次用邝斌的次小生成树模板 { double ans=0; memset(vis,false,sizeof(vis)); memset(Max,0,sizeof(Max)); memset(used,false,sizeof(used)); vis[0]=true; pre[0]=-1; for(int i=1; i<n; i++) { lowc[i]=cost[0][i]; pre[i]=0;//前驱,方便记录该点和前驱点的边是否被用过 } lowc[0]=0; for(int i=1; i<n; i++) { double minc=INF*1.0;//这里一定要乘以1.0 int p=-1; for(int j=0; j<n; j++) if(!vis[j]&&minc>lowc[j]) { minc=lowc[j]; p=j; } ans+=minc; vis[p]=true; used[p][pre[p]]=used[pre[p]][p]=true; for(int j=0; j<n; j++) { if(vis[j]&&j!=p)//这里一定要有j!=p Max[j][p]=Max[p][j]=max(Max[j][pre[p]],lowc[p]); if(!vis[j]&&lowc[j]>cost[p][j]) { lowc[j]=cost[p][j]; pre[j]=p; } } } return ans; } int main() { int n,t; cin>>t; while(t--) { cin>>n; for(int i=0; i<n; i++) { cin>>num[i].x>>num[i].y>>num[i].p; } for(int i=0; i<n; i++) { for(int j=i+1; j<n; j++) { cost[i][j]=cost[j][i]=Dis(num[i],num[j]);//因为给的是点的坐标,所以要在这里处理一下 } } double dis=prim(n); double sum=-1; for(int i=0; i<n; i++) for(int j=i+1; j<n; j++) { if(used[i][j]) sum=max(sum,1.0*(num[i].p+num[j].p)/(dis-cost[i][j])); else sum=max(sum,1.0*(num[i].p+num[j].p)/(dis-Max[i][j])); } printf("%.2f\n",sum); } return 0; }
相关文章推荐
- 详解次小生成树以及相关的C++求解方法
- 最小生成树算法之Prim算法
- 最小生成树算法——Prim和Kruskal算法的实现
- 初学图论-Kahn拓扑排序算法(Kahn's Topological Sort Algorithm)
- 初学图论-Bellman-Ford单源最短路径算法
- 初学图论-DAG单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现
- 封装好的Folyd建图,C++源码
- LCA模板
- 图论学习笔记之一——Floyd算法
- 【LCA】SPOJ QTREE2
- poj 3249 Test for Job 最长路
- 最小生成树
- HDU 2544
- Timus 1557 Network Attack DFS+各种各种...
- HDU1289 Tarjan-模板题
- Poj2638 网络流+最短路+二分答案
- Aizu1311 分层图最短路 (...大概)
- 最小生成树之prim算法