`
Simone_chou
  • 浏览: 184721 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

Qin Shi Huang's National Road System(最小生成树 + LCA)

    博客分类:
  • HDOJ
阅读更多

Qin Shi Huang's National Road System

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3750    Accepted Submission(s): 1305


Problem Description
During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---- they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the king of the kingdom Qin. Through 9 years of wars, he finally conquered all six other kingdoms and became the first emperor of a unified China in 221 BC. That was Qin dynasty ---- the first imperial dynasty of China(not to be confused with the Qing Dynasty, the last dynasty of China). So Ying Zheng named himself "Qin Shi Huang" because "Shi Huang" means "the first emperor" in Chinese.

Qin Shi Huang undertook gigantic projects, including the first version of the Great Wall of China, the now famous city-sized mausoleum guarded by a life-sized Terracotta Army, and a massive national road system. There is a story about the road system:
There were n cities in China and Qin Shi Huang wanted them all be connected by n-1 roads, in order that he could go to every city from the capital city Xianyang.
Although Qin Shi Huang was a tyrant, he wanted the total length of all roads to be minimum,so that the road system may not cost too many people's life. A daoshi (some kind of monk) named Xu Fu told Qin Shi Huang that he could build a road by magic and that magic road would cost no money and no labor. But Xu Fu could only build ONE magic road for Qin Shi Huang. So Qin Shi Huang had to decide where to build the magic road. Qin Shi Huang wanted the total length of all none magic roads to be as small as possible, but Xu Fu wanted the magic road to benefit as many people as possible ---- So Qin Shi Huang decided that the value of A/B (the ratio of A to B) must be the maximum, which A is the total population of the two cites connected by the magic road, and B is the total length of none magic roads.
Would you help Qin Shi Huang?
A city can be considered as a point, and a road can be considered as a line segment connecting two points.
 

 

Input
The first line contains an integer t meaning that there are t test cases(t <= 10).
For each test case:
The first line is an integer n meaning that there are n cities(2 < n <= 1000).
Then n lines follow. Each line contains three integers X, Y and P ( 0 <= X, Y <= 1000, 0 < P < 100000). (X, Y) is the coordinate of a city and P is the population of that city.
It is guaranteed that each city has a distinct location.
 

 

Output
For each test case, print a line indicating the above mentioned maximum ratio A/B. The result should be rounded to 2 digits after decimal point.
 

 

Sample Input
2
4
1 1 20
1 2 30
200 2 80
200 1 100
3
1 1 20
1 2 30
2 2 40
 

 

Sample Output
65.00
70.00
 

 

Source
 

 

Recommend
lcy

 

       题意:

       给出 T 组样例,每个样例都有 N 个点,后给出 N 个点的坐标和值。要求从中选出 n - 1 条路,选中其中一条为魔法路,这时候的 A = 魔法路所连接两个点的总和值, B = n - 1 条路的总和长度值 - 魔法路的长度值。求 A / B 最大。

 

       思路:

       最小生成树 + LCA。因为要求 A / B 最大,相当于求 B 最小,即求最小生成树。求完之后并没有结束,因为此刻还未能确定答案。之后开始枚举任意两个点,使这两个点连边(相当于在枚举魔法边),如果这两个点连接的边并不是生成树上的边,添加之后则必定会生成环,这时候要删除这个环上权值最大的那条边以保证 B 最小(B = min_tree - max_val);如果已经是生成树上的边,则直接删除这条边即可(B = min_tree - G [ i ] [ j ] )。找环则通过 LCA 寻找路径来找,边往上边比较最大值即可。注意数据类型!!!!因为保存边的时候一不小心用了 int 所以导致无限 WA。

 

        AC:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int VMAX = 1010;
const int EMAX = 1000010;

typedef struct {
    int root;
    double len;
} fath;

typedef struct {
    double x, y, num;
} node;

typedef struct {
    double len;
    int a, b;
} Map;

int G_ind, n;
double Min_sum;
node no[VMAX];
Map G[EMAX];
double G1[VMAX][VMAX];

int root[VMAX];

int ind;
int fir[VMAX], next[EMAX], v[EMAX];
double w[EMAX];

int cnt;
bool vis[VMAX];
int vs[VMAX * 2], dep[VMAX * 2], id[VMAX];
fath fa[VMAX];
int dp[VMAX * 2][25];

bool cmp (Map a, Map b) { return a.len < b.len; }

void init () {
    G_ind = ind = Min_sum = cnt = 0;
    for (int i = 1; i <= n; ++i) {
        fa[i].root = root[i] = i;
    }
    memset(fir, -1, sizeof(fir));
    memset(G1, 0, sizeof(G1));
    memset(vis, 0, sizeof(vis));
}

void add_edge (int f, int t, double val) {
    v[ind] = t;
    w[ind] = val;
    next[ind] = fir[f];
    fir[f] = ind;
    ++ind;
}

int Find (int x) {
    return root[x] == x ? x : root[x] = Find(root[x]);
}

void Min_tree () {
    sort(G, G + G_ind, cmp);

    int ans = 0;
    for (int i = 0; i < G_ind; ++i) {
        if (ans == n - 1) break;

        int a = Find(G[i].a);
        int b = Find(G[i].b);
        if (a != b) {
            ++ans;
            Min_sum += G[i].len;
            root[a] = b;
            add_edge(G[i].a, G[i].b, G[i].len);
            add_edge(G[i].b, G[i].a, G[i].len);
            G1[G[i].a][G[i].b] = G[i].len;
            G1[G[i].b][G[i].a] = G[i].len;
        } else continue;
    }

}

void dfs (int x, int d) {
    id[x] = cnt;
    dep[cnt] = d;
    vs[cnt++] = x;
    vis[x] = 1;

    for (int e = fir[x]; e != -1; e = next[e]) {
        int V = v[e];
        if (!vis[V]) {
            fa[V].root = x;
            fa[V].len = w[e];
            dfs (V, d + 1);
            vs[cnt] = x;
            dep[cnt++] = d;
        }
    }
}

void RMQ_init () {
    for (int i = 0; i < cnt; ++i) dp[i][0] = i;

    for (int j = 1; (1 << j) <= cnt; ++j) {
        for (int i = 0; i + (1 << j) < cnt; ++i) {
            int a = dp[i][j - 1];
            int b = dp[i + (1 << (j - 1))][j - 1];

            if (dep[a] < dep[b]) dp[i][j] = a;
            else dp[i][j] = b;
        }
    }
}

int RMQ (int L, int R) {
    int len = 0;
    while ((1 << (1 + len)) <= R - L + 1) ++len;

    int a = dp[L][len];
    int b = dp[R - (1 << len) + 1][len];

    if (dep[a] < dep[b]) return a;
    return b;
}

int LCA (int a, int b) {
    int L = min(id[a], id[b]);
    int R = max(id[a], id[b]);

    int node = RMQ(L, R);
    return vs[node];
}

double Find_max_road (int a, int b) {
    int lca = LCA(a, b);

    double Max = 0;
    while (a != lca) {
        Max = max(Max, fa[a].len);
        a = fa[a].root;
    }

    while (b != lca) {
        Max = max(Max, fa[b].len);
        b = fa[b].root;
    }

    return Max;
}

int main() {

    int t;
    scanf("%d", &t);

    while (t--) {
        scanf("%d", &n);

        init();

        for (int i = 1; i <= n; ++i) {
            scanf("%lf%lf%lf", &no[i].x, &no[i].y, &no[i].num);
        }

        for (int i = 1; i <= n - 1; ++i) {
            for (int j = i + 1; j <= n; ++j) {
                double x = (double)no[i].x - (double)no[j].x;
                double y = (double)no[i].y - (double)no[j].y;
                double len = sqrt(x * x + y * y);
                G[G_ind].a = i;
                G[G_ind].b = j;
                G[G_ind++].len = len;
            }
        }

        Min_tree();
        dfs (1, 1);
        RMQ_init();

        double ans = 0;
        for (int i = 1; i <= n - 1; ++i) {
            for (int j = i + 1; j <= n; ++j) {

                double Max;

                if (G1[i][j]) Max = G1[i][j];
                else Max = Find_max_road(i , j);

                double ans1 = Min_sum - Max;
                ans1 = (no[i].num + no[j].num) / ans1;

                ans = max(ans, ans1);
            }
        }

        printf("%.2lf\n", ans);

    }

    return 0;
}

 

 

分享到:
评论

相关推荐

    ACM2020倍增+LCA.pdf

    ACM2020倍增+LCA.pdf

    SAS+proc lca浅类别分析安装程序

    SAS+proc lca浅类别分析安装程序

    slca算法的实现

    一个很经典的论文,关于slca的论文,现在关于查询方面的知识,好多都是基于slca的

    ACM图论模板合集.pdf

    图论--最短路径生成树(最小边权和)模板 图论--最短路径生成树计数--模板 图论--生成树--次小生成树模板 图论--曼哈顿距离最小生成树模板 图论--生成树计数模板 连通性: 图论--割点--Tarjan模板...

    noip-数据结构习题.pdf

    货车运输 倍增 LCA+最小生成树 NOIP2013 2. 关押罪犯 并查集 NOIP2010 3. 舒适的路线 离线处理+最小生成树 CodeVS1001 By Hyt 4. 银河英雄传说 并查集 CodeVS1540 5. 受欢迎的牛 强联通分量 BZOJ1051 6. 部落划分 ...

    算法设计与分析-5图论桥pre ppt.pptx

    仅供参考,copy冲查重塔峰 算法设计与分析-5图论桥pre ppt.pptx (1) 图的连通性。 (2) 并查集的基本原理和...DFS、BFS、DSU生成生成树:连通性。 DSU:父亲数组father、查找find()、合并join() 路径压缩和按秩合并

    Pascal LCA 倍增法详解及代码

    LCA 详解以及完整代码详细介绍了倍增法的原理以及Pascal的完整代码 很好很强大

    RMQ与LCA ACM必备

    RMQ与LCA ACM必备RMQ与LCA ACM必备 RMQ与LCA ACM必备

    上海交通大学ACM算法模板

    16. 最小树形图O(N^3) 17. 最小树形图O(VE) 几何算法 1. 几何模板 2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉堆 7. ...

    RMQ和LCA详解

    关于RMQ和LCA的关系的知识,如何用RMQ和LCA的转换

    ACM 算法模板集

    16. 最小树形图O(N^3) 17. 最小树形图O(VE) 六. 几何算法 1. 几何模板 2. 球面上两点最短距离 3. 三点求圆心坐标 4. 三角形几个重要的点 七. 专题讨论 1. 树状数组 2. 字典树 3. 后缀树 4. 线段树 5. 并查集 6. 二叉...

    Tarjan 的 LCA 算法

    c++写的Tarjan 的 LCA 算法,最近公共祖先算法,可供算法学习参考

    日立LCA电气图纸(K3500490).pdf

    日立LCA电气图纸(K3500490).pdf

    LCA (最近公共祖先) Tarjan & 倍增

    LCA Tarjan: 实现原理 理解:离线算法,建好树后再查询,一次DFS 吧所有查询解决完。 时间复杂度:O(n+q); n个点 q次询问 补一下:链式向前星,并查集 ,Tarjan 代码 #include #include #include #include #...

    LCA RMQ 最小公共祖先 区间最小值

    原文来自于http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor。 翻译成中文。 LCA RMQ

    acm算法秘籍

    acm算法书,acmer必用的算法书。 目录 语言相关 常见基础错误 基础知识 枚举 模拟 排序 BFS DFS ...最近公共祖先 LCA 最小生成树 Kruskal 最小树形图 一般图的最大匹配 最大流 Dinic 最小割 费用流

    LCA265显示器应用

    用户数据的读取方法,如何对LCA265显示器传输数据。

    xml关键字查询求SLCA代码

    是对论文Efficient Keyword Search for Smallest LCAs in XML Databases的部分实现!

    中文LCA Training 2

    LCA 中文教程,内部资料--产品结构管理,还不错啊,可以看下

    LCA生命周期评价PPT课件.ppt

    LCA生命周期评价,LCA生命周期评价课件,LCA生命周期评价PPT

Global site tag (gtag.js) - Google Analytics