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. Android调用系统相机、自己定义相机、处理大图片

    Android调用系统相机和自己定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,而且因为涉及到要把拍到的照片显示出来,该样例也会涉及到Android载入大图片时候的处 ...

  2. D3D 练习小框架

    自己练习D3D 程序搭的小框架,记录在这里,将来看到好回顾自己独自摸索的苦逼样子. #pragma once #pragma comment(lib,"d3d9.lib") #pr ...

  3. android电池充电以及电量检测驱动分析

    前段时间比较烦躁,各种不想学习不想工作,于是休息了几天.这几天又下来任务了--调试充电电路和电池电量检测电路,于是又开始工作,顺便把调试过程记录下来. 平台: cpu        飞思卡尔imx6q ...

  4. 一切皆为 JavaScript

    JavaScript起源于Netscape公司的LiveScript语言,这是一种基于对象和事件驱动的client脚本语言.最初的设计是为了检验HTML表单输入的正确性. 早些年,JavaScript ...

  5. HDU 1007 近期点对

    分治法求近期点对 递归将点不断分成小组.计算最短距离.此时的最短距离不过两点都属两块的某一块(这里的切割点是mid点). 还须要考虑两点分属两块的情况. 这时对于选点则把范围缩小到了以mid为中心. ...

  6. 用Feed43为随意站点定制RSS feed教程~

     用Feed43为随意站点定制RSS feed教程- Feed43--自己定义RSS种子的免费工具中笔者的最爱,确切来讲Feed43不适合心脏衰弱者.通过它的服务,我能够很好地控制种子的终于样式,当然 ...

  7. Android 手势&amp;触摸事件 MotionEvent

    1.http://blog.csdn.net/omg_2012/article/details/7881443 这篇相当好啊 2.http://blog.csdn.net/android_tutor/ ...

  8. Codeforces 358 D. Dima and Hares

    dp[i][0]表示i号兔子先于i-1号兔子喂食,dp[i][1]反过来. 倒着DP D. Dima and Hares time limit per test 2 seconds memory li ...

  9. JAVA WEB开发环境搭建教程

    一.下载安装JDK,配置好环境变量.(例如我JDK安装的目录为:C:\Program Files (x86)\Java\jdk1.6.0_10     ) 点击我的电脑-属性-系统设置(高级系统设置) ...

  10. WPF 设置WebBrowser控件不弹脚本错误提示框

    using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.N ...