【问题标题】:Count the number of unordered pairs in an un-directed graph计算无向图中无序对的数量
【发布时间】:2015-04-23 15:35:02
【问题描述】:

可以找到问题的链接here

问题陈述

汉堡镇是一个由 N 个特殊路口和 N−1 个 途径。每对之间只有一条最短路径 路口。结点 i 位于 (xi,yi) 和之间的距离 两个路口 i,j 由出租车几何定义。

蒂姆最近聘请了一辆出租车担任出租车司机。他的 车辆很便宜,但有一个很大的缺陷。它只能驱动H 加油前水平单位和垂直单位。

如果客户想从第 i 个路口被带到另一个路口 路口 j,那么这辆车只能在这条路线上行驶,当且仅当 水平距离之和和垂直距离之和 该路径分别小于或等于H和V。

此外,任何两个路口之间都有一条独特的路径。

现在他有将车辆退回给卖家的想法。 但他首先想知道,这是否值得。这就是为什么他想要 知道无序对 (i,j) 的数量,使得它不是 可以将客户从路口 i 带到路口 j。

约束

2 ≤ N ≤ 10^5

0 ≤ H,V ≤ 10^14

0 ≤ xi,yi ≤ 10^9

我已经用递归解决了这个问题。但是在某些测试用例中,我的代码超时了。

import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;

public class Solution {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        long H = in.nextLong();
        long V = in.nextLong();
        List<Vertex> vertex = new ArrayList<>();

        for (int i=0; i < N; i++) {
            Vertex vx = new Vertex(in.nextLong(), in.nextLong());
            vertex.add(vx);
        }
        for (int i=0; i < N-1; i++) {
            int fromPath = in.nextInt()-1;
            int toPath = in.nextInt()-1;
            vertex.get(fromPath).neighbours.add(vertex.get(toPath));
            vertex.get(toPath).neighbours.add(vertex.get(fromPath));
        }

        long count = 0;

        for (int i=0; i < N; i++) {
            count += (N - findUnorderedPairs(vertex.get(i), null, 0, 0, H, V));
        }

        System.out.println(count/2);
        int temp = 0;

    }

    private static long findUnorderedPairs(Vertex vertex, Vertex previousVertex, long hor, long vert, long H, long V) {
        if (hor > H || vert > V) {
            return 0;
        }

        long result = 1;

        for (Vertex v : vertex.neighbours) {
                result += (v != previousVertex) ? findUnorderedPairs(v, vertex, hor + Math.abs(vertex.x - v.x), vert + Math.abs(vertex.y - v.y), H, V) : 0;

        }

        return result;
    }

    private static class Vertex {
        private long x;
        private long y;
        public ArrayList<Vertex> neighbours;

        public Vertex(long x, long y) {
            this.x = x;
            this.y = y;
            neighbours = new ArrayList<>();
        }
    }
}

我也尝试过 Dijkstras 的实现,但也没有运气。

任何关于如何实现更快解决方案的建议将不胜感激。

【问题讨论】:

  • 试试kruskal的算法
  • 描述自相矛盾。在第一段中,它说:“每对路口之间恰好有一条最短路径。”后来,它说:“而且,任何两个路口之间都有一条独特的路径。”那么它是什么?
  • @JimMischel 我看不出有什么矛盾,there is a unique path between any two junctions 表示这是一棵连通树,唯一的路径也是最短路径。
  • @PhamTrung:你是对的。 “只有一条最短路径”这一说法只是无关紧要的信息。阅读它给人的印象是这是某种优化问题(即找到最短路径)。

标签: java algorithm optimization timeout


【解决方案1】:

这是一个O(n log^2 n) 解决方案(它对于这个问题来说已经足够快了:我设法使用它被接受了,但我不会在这里发布我的代码,因为我认为理解算法本身比理解算法更有用看看它的实现)。

  1. 让我们使用树的质心分解。您可以在此处阅读更多信息:http://www.ioi2011.or.th/hsc/tasks/solutions/race.pdf

  2. 如何合并子树的解决方案?我们可以将每个点表示为一对(x, y),其中xy 是通过xy 轴从该点到当前根的距离。对于每个点,我们要计算x1 + x2 &lt;= Hy1 + y2 &lt;= W 等其他点的数量,或者换句话说,x1 &lt;= H - x2y1 &lt;= W - y2。因此,一个固定点的所有“好”点都位于(0, 0, H - x, W - y) 矩形中。计算这些点的数量是一个标准问题,它可以在O(n log n) 时间内使用带有treap(或坐标压缩和二叉索引树)的扫描线来解决。

  3. 这里有一个小问题:我们不应该计算来自同一子树的点。我们可以通过对每个子树运行相同的算法并从答案中减去结果来轻松修复它。

  4. 合并步骤在O(n log n) 时间内完成。因此,总时间复杂度为O(n log^2 n)

我知道这个解释不是很详细,但在我看来,使用这里描述的关键思想提出一个完整的解决方案应该不会太难。

【讨论】:

  • 谢谢你。今天晚些时候我会尝试一下这个想法:)
猜你喜欢
  • 2021-09-21
  • 2020-08-12
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多