zoukankan      html  css  js  c++  java
  • Qin Shi Huang's National Road System HDU

    原题链接

    • 题意:遍历每个非关键边,预处理出来两个 (MST) 中的点到最近公共祖先的最长的边的距离,然后就是 (frac{cnt}{sum - Max_{i,j}}) 枚举 (i,j) 即可,简直就和求最小生成树的过程一模一样。
    • 代码:
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    
    using namespace std;
    const int N = 1111;
    const int M = 2 * N * N;
    int cnt = 0;
    double sum = 0;
    int h[N], to[M], ne[M], idx;
    double W[M];
    int dep[N];
    int f[N][20];
    double g[N][20];
    void add(int u, int v ,double w) {
        ne[idx] =h[u], to[idx] = v, W[idx]  =w, h[u] = idx++;
    }
    void dfs(int u, int fa) {
        if (fa == -1)dep[u] = 1;
        else dep[u] = dep[fa] + 1;
        for (int i = 1; i <= 13; i ++) {
            f[u][i] = f[f[u][i-1]][i-1];
            g[u][i] = max(g[u][i-1],g[f[u][i-1]][i-1]);
        }
        for (int i = h[u]; i!= -1; i = ne[i]) {
            int v = to[i];
            if (dep[v] == 0) {
                f[v][0] = u;
                g[v][0] = W[i];
                dfs(v, u);
            }
        }
        
    }
    struct node {
        double x, y;
        int cnt;
    }p[N];
    struct edge {
        int u, v;double w;
        int cnt;
    }e[M];
    bool cmp(edge a, edge b){return a.w < b.w;}
    int fa[N];
    int Find(int x){return fa[x] == x?x:fa[x] = Find(fa[x]);}
    double dis(node a, node b) {
        return sqrt((a.x- b.x)*(a.x-b.x) + (a.y - b.y) * (a.y - b.y));
    }
    void un(int i) {
        int fx = Find(e[i].u);
        int fy = Find(e[i].v);
        if (fx == fy)return;
        fa[fx] = fy;
        add(e[i].u, e[i].v, e[i].w);
        add(e[i].v, e[i].u, e[i].w);
        sum += e[i].w;
    }
    double lca(int u, int v) {
        if (dep[u] < dep[v])swap(u, v);
        double ret = -1;
        for (int i = 14; i >= 0; i--) {
            if (dep[f[u][i]] >= dep[v]) {
                ret = max(ret, g[u][i]);
                u = f[u][i];
            }
        }
        if (u == v)return ret;
        for (int i = 14; i >= 0; i--) {
            if (f[u][i] != f[v][i]) {
                ret = max(ret, max(g[u][i], g[v][i]));
                u = f[u][i], v = f[v][i];
            }
        }
        ret = max(ret, max(g[u][0], g[v][0]));
        return ret;
    }
    void solve() {
        int n;scanf("%d", &n);
        for (int i = 1; i <= n; i ++) {
            scanf("%lf%lf%d", &p[i].x, &p[i].y,&p[i].cnt);
            fa[i] = i;
        }
        int m = 0;cnt = 0;
        sum = 0;
        double ans = -1;
        memset(h, -1, sizeof h);idx = 0;
        memset(dep, 0, sizeof dep);
        for (int i = 1; i <= n; i ++) {
            for (int j = i + 1; j <= n; j ++) {
                e[++m] = {i, j, dis(p[i], p[j])};
            }
        }
        sort(e + 1, e + 1 +  m, cmp);
        for (int i = 1; i <= m; i ++) {
            un(i);
        }
        dfs(1, -1);
        for (int i = 1; i <= n; i ++) {
            for (int j = i + 1; j <=n; j ++) {
                ans = max(ans,(double)( p[i].cnt + p[j].cnt*1.0 )/(sum - lca(i, j) ) );
            }
        }
        printf("%.2lf
    ", ans);
    }
    signed main() {
        int t;scanf("%d", &t);
        while (t--) {
            solve();
        }
        return 0;
    }
    
  • 相关阅读:
    LeetCode 32. 最长有效括号(Longest Valid Parentheses)
    LeetCode 141. 环形链表(Linked List Cycle)
    LeetCode 160. 相交链表(Intersection of Two Linked Lists)
    LeetCode 112. 路径总和(Path Sum)
    LeetCode 124. 二叉树中的最大路径和(Binary Tree Maximum Path Sum)
    LightGBM新特性总结
    sql service 事务与锁
    C#泛型实例详解
    C# 中的委托和事件(详解)
    C# DateTime日期格式化
  • 原文地址:https://www.cnblogs.com/Xiao-yan/p/14635770.html
Copyright © 2011-2022 走看看