hdu4081 秦始皇修路(次小生成树)
题目ID:hdu4081 秦始皇修路
题目链接:点击打开链接
题目大意:给你若干个坐标,每个坐标表示一个城市,每个城市有若干个人,现在要修路,即建一个生成树,然后有一个魔法师可以免费造路(不消耗人力),然后秦始皇希望这条免费的路A/B最大,A是这条路连接的两个城市人口和,B是出了这条路以外所有路的总长度。让你输出这个A/B。
思路:这道题数据量不大,可以两重for算出点和点之间的距离,建图。A/B这个式子A不难算,B的话作为分母希望越小越好,但是和分子在一起,最小的B未必是最好的B。所以需要枚举所有的A-B组合,最大的那个就是答案。很自然想到最小生成树,假设最小生成树总长为tmp,免费造的这条边如果是最小生成树中的路,那么ratio=A/(tmp-g[i][j]),g[i][j]就是图上的距离;如果造的路不是最小生成树中的路,那么ratio=A/(tmp-path[i][j]),path表示加入i-j这条边后,会形成一个环,这个环中除了我新加的边以外 最长的那个边就是path[i][j],这个思路和计算最小生成树的想法很像。而判断是否在最小生成树中使用过,就用一个used[][]来表示就可以了。
核心代码:
double prim(int v) {
int i,j,u;
double sum,tmp;
sum=0;
memset(vis,0,sizeof(vis));
memset(used,0,sizeof(used));
memset(path,0,sizeof(path));
for(i=1; i<=n; i++) {
dis[i]=g[v][i];
pre[i]=1;//pre[i]表示 将i点联系到生成树点集里的那个点;
}
vis[v]=1;
for(i=1; i<n; i++) {
u=v;
tmp=INF;
for(j=1; j<=n; j++)
if(dis[j]<tmp&&vis[j]==0) {
tmp=dis[j];
u=j;
}
sum+=tmp;
vis[u]=1;
used[u][pre[u]]=used[pre[u]][u]=1;//表示最小生成树中 u和pre[u]是其中的一条路
for(j=1; j<=n; j++) {
if(vis[j]&&j!=u) //j已经在树上 所以path[j][pre[u]]之前已经计算过了(j和pre[u]都在树上了)
path[u][j]=path[j][u]=max(path[j][pre[u]],dis[u]);// u-j环 的最大权值=max(u到点集(pre[u])的距离,j-pre[u]环的最大权值);
if(!vis[j]) {
if(dis[j]>g[u][j]) {
dis[j]=g[u][j];
pre[j]=u;//若松弛 则更新
}
}
}
}
return sum;
}
这样处理完可以得到tmp和path[i][j],然后就是
A=max(A,(a[i].peo+a[j].peo)/(tmp-g[i][j]))和
A=max(A,(a[i].peo+a[j].peo)/(tmp-path[i][j]))的区别了
具体看完整代码:
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const double INF=0x3f3f3f3f;
using namespace std;
double dis[1005],path[1005][1005],g[1005][1005];
int n,m,pre[1005],vis[1005],used[1005][1005];
double get(double x1,double y1,double x2,double y2) {
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double prim(int v) {
int i,j,u;
double sum,tmp;
sum=0;
memset(vis,0,sizeof(vis));
memset(used,0,sizeof(used));
memset(path,0,sizeof(path));
for(i=1; i<=n; i++) {
dis[i]=g[v][i];
pre[i]=1;//pre[i]表示 将i点联系到生成树点集里的那个点;
}
vis[v]=1;
for(i=1; i<n; i++) {
u=v;
tmp=INF;
for(j=1; j<=n; j++)
if(dis[j]<tmp&&vis[j]==0) {
tmp=dis[j];
u=j;
}
sum+=tmp;
vis[u]=1;
used[u][pre[u]]=used[pre[u]][u]=1;//表示最小生成树中 u和pre[u]是其中的一条路
for(j=1; j<=n; j++) {
if(vis[j]&&j!=u) //j已经在树上 所以path[j][pre[u]]之前已经计算过了(j和pre[u]都在树上了)
path[u][j]=path[j][u]=max(path[j][pre[u]],dis[u]);// u-j环 的最大权值=max(u到点集(pre[u])的距离,j-pre[u]环的最大权值);
if(!vis[j]) {
if(dis[j]>g[u][j]) {
dis[j]=g[u][j];
pre[j]=u;//若松弛 则更新
}
}
}
}
return sum;
}
struct dian {
double x,y;
int peo;
} a[1005];
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
for(int i=1; i<=n; i++) {
scanf("%lf%lf%d",&a[i].x,&a[i].y,&a[i].peo);
}
for(int i=1; i<=n; i++) {
for(int j=i+1; j<=n; j++) {
g[i][j]=g[j][i]=get(a[i].x,a[i].y,a[j].x,a[j].y);
}
}
double tmp=prim(1);
double A=0;
for(int i=1; i<=n; i++) {
for(int j=i+1; j<=n; j++) {
if(used[i][j]) {//在树上 取消的边就是图上的距离
A=max(A,(a[i].peo+a[j].peo)/(tmp-g[i][j]));
} else {//不在树上 取消的边是环中的最大权值
A=max(A,(a[i].peo+a[j].peo)/(tmp-path[i][j]));
}
}
}
printf("%.2f\n",A);
}
}
hdu4081 秦始皇修路(次小生成树)的更多相关文章
- HDU-4081.Qinshihuang'sNationalRoadSystem(次小生成树变种)
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- hdu4081 次小生成树变形
pid=4081">http://acm.hdu.edu.cn/showproblem.php?pid=4081 Problem Description During the Warr ...
- Nyoj 修路方案(次小生成树)
描述 南将军率领着许多部队,它们分别驻扎在N个不同的城市里,这些城市分别编号1~N,由于交通不太便利,南将军准备修路. 现在已经知道哪些城市之间可以修路,如果修路,花费是多少. 现在,军师小工已经找到 ...
- HDU4081 Qin Shi Huang's National Road System —— 次小生成树变形
题目链接:https://vjudge.net/problem/HDU-4081 Qin Shi Huang's National Road System Time Limit: 2000/1000 ...
- nyoj_118:修路方案(次小生成树)
题目链接 题意,判断次小生成树与最小生成树的权值和是否相等. 豆丁文档-- A-star和第k短路和次小生成树和Yen和MPS寻路算法 法一: 先求一次最小生成树,将这棵树上的边加入一个向量中,再判断 ...
- hdu4081次小生成树
先求一遍最小生成树,然后遍历所有边,如果这条边在最小生成树中就直接减去这条边的距离,如果不在最小生成树中,那么就构成了一个环,此时需要减去最小生成树中最大的边,即求次小生成树时的maxx, 有一点要注 ...
- 修路方案 Kruskal 之 次小生成树
次小生成树 : Kruskal 是先求出来 最小生成树 , 并且记录下来所用到的的边 , 然后再求每次都 去掉最小生成树中的一个边 , 这样求最小生成树 , 然后看能不能得到 和原来最小生成树一样的 ...
- hdu4081 Qin Shi Huang's National Road System 次小生成树
先发发牢骚:图论500题上说这题是最小生成树+DFS,网上搜题解也有人这么做.但是其实就是次小生成树.次小生成树完全当模版题.其中有一个小细节没注意,导致我几个小时一直在找错.有了模版要会用模版,然后 ...
- HDU 4081Qin Shi Huang's National Road System(次小生成树)
题目大意: 有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点.秦始皇希望这所有n-1条路长度之和最短.然后徐福突然有冒出来,说是他有魔法,可以不用人力.财力就变 ...
随机推荐
- IDEA中Git实战
工作中多人使用版本控制软件协作开发,常见的应用场景归纳如下: 假设小组中有两个人,组长小张,组员小袁 场景一:小张创建项目并提交到远程Git仓库 场景二:小袁从远程Git仓库上获取项目源码 场景三:小 ...
- buntu下shell脚本运行异常:bash和…
转载于:http://www.51testing.com/?uid-225738-action-viewspace-itemid-208702 我用bash到语法写了一个shell脚本(准确的说是把书 ...
- springmvc 处理器方法返回的是string 重定向到处理器方法
- to_date() 、to_char()、to_number的FMT格式
元素 含义 结果:2018/01/12(周五) - / , . ; : (6中不同分隔符) 分隔符 y 显示一位年份 8 yy 显示二位年 ...
- JVM实用参数(二)参数分类和即时(JIT)编译器诊断
JVM实用参数(二)参数分类和即时(JIT)编译器诊断 作者: PATRICK PESCHLOW 原文地址 译者:赵峰 校对:许巧辉 在这个系列的第二部分,我来介绍一下HotSpot J ...
- [poj3041]Asteroids(二分图的最小顶点覆盖)
题目大意:$N*N$的网格中有$n$颗行星,若每次可以消去一整行或一整列,求最小的攻击次数使得消去所有行星. 解题关键:将光束当做顶点,行星当做连接光束的边建图,题目转化为求该图的最小顶点覆盖,图的最 ...
- C++面向对象类的实例题目一
在一个程序中,实现如下要求: (1)构造函数重载 (2)成员函数设置默认参数 (3)有一个友元函数 (4)有一个静态函数 (5)使用不同的构造函数创建不同对象 code: #include<io ...
- 分布式锁2 Java非常用技术方案探讨之ZooKeeper 【转载】
前言: 由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.以自己结合实际工作中的一些经验和网上看到的一些资料 ...
- Ubuntu jdk安装详细
安装jdk步骤: 1.首先连接130的ip地址,进去Tools拷贝jdk压缩文件(Tools中已经有下载好的jdk版本,也可自己另行下载) 2.将拷贝好的压缩文件解压 tar -zxvf 压缩文件名 ...
- 【Android学习】三种布局<include />、<merge />、<ViewStub />
1.布局重用<include /> <include />标签能够重用布局文件,使用起来非常简单 <include layout="@layout/layout ...