uvaLive5713

修建道路使得n个点任意两点之间都可以连通,每个点有都有一定的人口,现在可以免费修一条道路,

A是免费修的道路两端结点的人口之和, B的其它不是免费修道路的长度的总和

要求的是A/B的最短值。

B其实就是最小生成树删除一条边只有的权值之和B。 只要我们知道生成树上任意两点之间的最长边,那么只要在这两点之间修一条边,

然后删除最长边,它还是一棵树。 而已这时候的权值之和是B-maxCost[u][v]

那么 答案就是min{p[u][v] / (B-maxCost[u][v])} , 枚举u,v的时间复杂度是O(n*n)。

至于得到maxCost[u][v] 只要在得到最小生成树之后,一遍dfs就可以求出

求解的方法是:当访问一个新节点时,计算所有已经访问过的结点到这个结点的最小权值

max[u][x] = maxCost[x][u] = max(maxCost[x][fa],edge(u,fa))

u是当前访问的结点,fa是u的父亲, x是所有已经访问过的结点。

(其实就是两个嵌套的循环,只不过是在树上循环罢了)

总的时间复杂度是n*n + e*loge     常数没有计算进去。

n*n和eloge 最大时都是1000多w, 3s的时间,足够了

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
#pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
const int INF = <<;
/* */
const int N = + ;
struct Edge
{
int form, to, p;
double dist;
bool operator<(const Edge&rhs)const
{
return dist < rhs.dist;
}
}a[N*N];
int x[N], y[N], p[N];
int father[N];
double maxCost[N][N];
int p2[N][N];
vector<Edge> g[N];
vector<int> st;
int find(int x)
{
if (x == father[x])
return x;
return father[x] = find(father[x]);
}
double kruskal(int n)
{
double sum = ;
for (int i = ; i < n; ++i)
{
int fx = find(a[i].form);
int fy = find(a[i].to);
if (fx != fy)
{
//记录生成树,用来等下dfs
g[a[i].form].push_back(a[i]);
swap(a[i].form, a[i].to);
g[a[i].form].push_back(a[i]);
sum += a[i].dist;
father[fx] = fy;
}
}
return sum;
} /*
这个dfs其实就是给定一棵树,然后求任意两点之间的最大边权, 因为是任意两点, 那么时间复杂度无疑就是O(n*n)
*/
void dfs(int u, int fa, double dis)
{
if (fa!=-)
for (int i = ; i < st.size(); ++i)
{
int x = st[i];
maxCost[x][u] = maxCost[u][x] = max(maxCost[x][fa], dis);
}
st.push_back(u);
for (int i = ; i < g[u].size(); ++i)
{
int v = g[u][i].to;
if (v == fa) continue;
dfs(v, u, g[u][i].dist);
}
}
int main()
{
int t, n, cnt;
double B;
scanf("%d", &t);
while (t--)
{
scanf("%d", &n);
cnt = ;
st.clear();
for (int i = ; i < n; ++i)
{
father[i] = i;
g[i].clear();
scanf("%d%d%d", &x[i], &y[i], &p[i]);
}
for (int i = ; i < n; ++i)
{
for (int j = i + ; j < n; ++j)
{
p2[i][j] = p2[j][i] = p[i] + p[j];
//边集数组
a[cnt].form = i;
a[cnt].to = j;
a[cnt].p = p[i] + p[j];
a[cnt++].dist = sqrt((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]));
}
}
sort(a, a + cnt);
B = kruskal(cnt);
dfs(, -, );
double ans = ; //枚举在哪两个之间建免费的道路
for (int i = ; i < n; ++i)
for (int j = i + ; j < n; ++j)
ans = max(ans, p2[i][j] / (B - maxCost[i][j]));
printf("%.2lf\n", ans);
}
return ;
}

uvaLive5713 次小生成树的更多相关文章

  1. UVALive-5713 Qin Shi Huang's National Road System (次小生成树)

    题目大意:有n个城市,要修一些路使得任意两个城市都能连通.但是有人答应可以不计成本的帮你修一条路,为了使成本最低,你要慎重选择修哪一条路.假设其余的道路长度为B,那条别人帮忙修的道路两端城市中的总人口 ...

  2. HDU 4081Qin Shi Huang's National Road System(次小生成树)

    题目大意: 有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点.秦始皇希望这所有n-1条路长度之和最短.然后徐福突然有冒出来,说是他有魔法,可以不用人力.财力就变 ...

  3. POJ1679 The Unique MST[次小生成树]

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28673   Accepted: 10239 ...

  4. The Unique MST(次小生成树)

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22335   Accepted: 7922 Description Give ...

  5. URAL 1416 Confidential --最小生成树与次小生成树

    题意:求一幅无向图的最小生成树与最小生成树,不存在输出-1 解法:用Kruskal求最小生成树,标记用过的边.求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就 ...

  6. POJ1679The Unique MST(次小生成树)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25203   Accepted: 8995 D ...

  7. [kuangbin带你飞]专题八 生成树 - 次小生成树部分

    百度了好多自学到了次小生成树 理解后其实也很简单 求最小生成树的办法目前遇到了两种 1 prim 记录下两点之间连线中的最长段 F[i][k] 之后枚举两点 若两点之间存在没有在最小生成树中的边 那么 ...

  8. URAL 1416 Confidential(次小生成树)

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1416 Zaphod Beeblebrox — President of the Impe ...

  9. ACM题目————次小生成树

    Description 最小生成树大家都已经很了解,次小生成树就是图中构成的树的权值和第二小的树,此值也可能等于最小生成树的权值和,你的任务就是设计一个算法计算图的最小生成树. Input 存在多组数 ...

随机推荐

  1. IT行业,需要经常锻炼,开篇从本钱开始

    今天下完班,和部门兄弟一起去打了两小时乒乓球,大汗淋漓,很痛快. 败给了两个高手,感觉年龄大了些,灵活性没有以前那么好了. 想想以前读书时,在整个学校都叱诧风云,如今即败给了几个老手,唉. 看来以后要 ...

  2. EFI/GPT探索(为何win7分区时创建100M隐藏分区)

    EFI/GPT探索(为何win7分区时创建100M隐藏分区) 转自 http://blog.tomatoit.net/article.asp?id=348 EFI/GPT是新一代的固件/启动管理技术, ...

  3. VC++ WIN32 sdk实现按钮自绘详解 之二.

    网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片:    首先建立一个标准的Win32 Application 工程.选择a simple Wi ...

  4. jar包生制作几种方法,jar包导出三种方法:eclipse导出、jar命令、FatJar插件

    Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法 方案一:用Eclipse自带的Export功能 步骤1:准备主清单文件 “MANIFEST.MF”, 由于是打包引用了第三 ...

  5. 修改Hosts文件

    Hosts文件是一个用于存储计算机网络中节点信息的文件,它可以将主机名映射到相应的IP地址,实现DNS的功能,它可以由计算机的用户进行控制. Hosts文件的存储位置在不同的操作系统中并不相同,甚至不 ...

  6. Objective-C中经常使用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect

    Objective-C中经常使用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect 1   NSRange NSRange 的原型为 typedef struct _N ...

  7. poj 1743 男人八题之后缀数组求最长不可重叠最长重复子串

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 14874   Accepted: 5118 De ...

  8. codeforces 659B Qualifying Contest

    题目链接:http://codeforces.com/problemset/problem/659/B 题意: n个人,m个区.给出n个人的姓名(保证不相同),属于的区域,所得分数.从每个区域中选出成 ...

  9. [Android学习笔记]view的layout过程学习

    View从创建到显示到屏幕需要经历几个过程: measure -> layout -> draw measure过程:计算view所占屏幕大小layout过程:设置view在屏幕的位置dr ...

  10. 开启cocos2dx 3.0的Console功能

    下面内容用于自己知识的备忘,想看具体内容,请參照例如以下地址. 原英文文地址: http://discuss.cocos2d-x.org/t/cocos3-0-tutorial-console-tut ...