• 图-1400. 图的费马点


    2020-04-06 18:45:31

    问题描述:

    有一个无向无环连通图,每条边通过两个顶点x[i],y[i]来描述,每条边的长度通过d[i]来描述。
    求这样的一个点p,使得其他点到p的距离和最小,如果有多个这样的点p,返回编号最小的。

    样例

    样例 1:

    给出 x = `[1]`, y = `[2]`, d = `[3]`, 返回 `1`。
    输入:
    [1]
    [2]
    [3]
    输出:
    1
    
    解释:
    其他点到 1 的距离和为 3,其他点到 2 的距离和为 3,1 的编号较小。

    样例 2:

    给出 x = `[1,2,2]`, y = `[2,3,4]`, d = `[1,1,1]`, 返回 `2`。
    输入:
    [1,2,2]
    [2,3,4]
    [1,1,1]
    输出:
    2
    
    解释:
    其他点到 1 的距离和为 5,其他点到 2 的距离和为 3,其他点到 3 的距离和为 5,其他点到 4 的距离和为 5。

    注意事项

    • 2 <= n, d[i] <= 10^5
    • 1 <= x[i], y[i] <= n

    问题求解:

    和树的路径和类似,只是这里边有权值。

    时间复杂度:O(n)

        Map<Integer, Set<int[]>> graph = new HashMap<>();
        Map<Integer, Integer> cnt = new HashMap<>();
        Map<Integer, Long> sum = new HashMap<>();
        List<long[]> record = new ArrayList<>();
        public int getFermatPoint(int[] x, int[] y, int[] d) {
            for (int i = 0; i < x.length; i++) {
                int from = x[i];
                int to = y[i];
                int w = d[i];
                if (!graph.containsKey(from)) graph.put(from, new HashSet<>());
                if (!graph.containsKey(to)) graph.put(to, new HashSet<>());
                graph.get(from).add(new int[]{to, w});
                graph.get(to).add(new int[]{from, w});
            }
            dfs1(x[0], -1);
            dfs2(x[0], -1);
            Collections.sort(record, (long[] o1, long[] o2) -> o1[0] == o2[0] ? Long.compare(o1[1], o2[1]) : Long.compare(o1[0], o2[0]));
            return (int)record.get(0)[1];
        }
        
        private void dfs2(int root, int parent) {
            record.add(new long[]{sum.get(root), root});
            for (int[] next : graph.get(root)) {
                if (next[0] == parent) continue;
                long w = (long)next[1];
                long curr = sum.get(root) + (long)(cnt.size() - cnt.get(next[0]) * 2) * w;
                sum.put(next[0], curr);
                dfs2(next[0], root);
            }
        }
        
        private void dfs1(int root, int parent) {
            int curr_cnt = 1;
            long curr_sum = 0;
            for (int[] next : graph.get(root)) {
                if (next[0] == parent) continue;
                dfs1(next[0], root);
                curr_cnt += cnt.get(next[0]);
                curr_sum += sum.get(next[0]) + (long)next[1] * (long)cnt.get(next[0]);
            }
            cnt.put(root, curr_cnt);
            sum.put(root, curr_sum);
        }
    

      

  • 相关阅读:
    [JSOI2016]最佳团体
    CF125E MST Company
    CF482C Game with Strings
    CF379F New Year Tree
    CF1051F The Shortest Statement
    小a和uim之大逃离
    新魔法药水
    翻硬币
    [CQOI2017]小Q的棋盘
    UVA11729突击战
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12643576.html
Copyright © 2020-2023  润新知