Exemplo n.º 1
0
def is_simple(polygon):
    """Test if a rectilinear polygon is is_simple

    :param polygon: list of points as (x,y) pairs along the closed polygon
    :returns: True if the segements do not intersect
    :complexity: O(n log n) for n=len(polygon)
    """
    n = len(polygon)
    order = list(range(n))
    order.sort(key=lambda i: polygon[i])  # ordre lexicographique
    rank_to_y = list(set(p[1] for p in polygon))
    rank_to_y.sort()
    y_to_rank = {rank_to_y[i]: i for i in range(len(rank_to_y))}
    S = RangeMinQuery([0] * len(rank_to_y))  # structure balayage
    for i in order:
        x, y = polygon[i]
        rank = y_to_rank[y]
        #                             -- type de point
        right_x = max(polygon[i - 1][0], polygon[(i + 1) % n][0])
        left = x < right_x
        below_y = min(polygon[i - 1][1], polygon[(i + 1) % n][1])
        high = y > below_y
        if left:  # il ne faut pas encore y dans S
            if S[rank]:
                return False  # inters. entre deux segm. horiz.
            S[rank] = -1  # ajouter y à S
        else:
            S[rank] = 0  # enlever y de S
        if high:
            lo = y_to_rank[below_y]  # vérifier S entre lo + 1 et rank - 1
            if (below_y != last_y or last_y == y
                    or rank - lo >= 2 and S.range_min(lo + 1, rank)):
                return False  # inters. entre segm. horiz. et vertic.
        last_y = y  # mémoriser pour prochaine itération
    return True
    def __init__(self, graph):
        """builds the structure from a given tree

        :param graph: adjacency matrix of a tree
        :complexity: O(n log n), with n = len(graph)
        """
        n = len(graph)
        dfs_trace = []
        self.last = [None] * n
        to_visit = [(0, 0, None)]  # sommet 0 est la racine
        next = [0] * n
        while to_visit:
            level, node, father = to_visit[-1]
            self.last[node] = len(dfs_trace)
            dfs_trace.append((level, node))
            if next[node] < len(graph[node]) and \
               graph[node][next[node]] == father:
                next[node] += 1
            if next[node] == len(graph[node]):
                to_visit.pop()
            else:
                neighbor = graph[node][next[node]]
                next[node] += 1
                to_visit.append((level + 1, neighbor, node))
        self.rmq = RangeMinQuery(dfs_trace, (float('inf'), None))
Exemplo n.º 3
0
def is_simple(polygon):
    """Test if a rectilinear polygon is is_simple

    :param polygon: list of points as (x,y) pairs along the closed polygon
    :returns: True if the segements do not intersect
    :complexity: O(n log n) for n=len(polygon)
    """
    n = len(polygon)
    order = list(range(n))
    order.sort(key=lambda i: polygon[i])         # ordre lexicographique
    rank_to_y = list(set(p[1] for p in polygon))
    rank_to_y.sort()
    y_to_rank = {rank_to_y[i]: i for i in range(len(rank_to_y))}
    S = RangeMinQuery([0] * len(rank_to_y))      # structure balayage
    for i in order:
        x, y = polygon[i]
        rank = y_to_rank[y]
        #                             -- type de point
        right_x = max(polygon[i - 1][0], polygon[(i + 1) % n][0])
        left   = x < right_x
        below_y = min(polygon[i - 1][1], polygon[(i + 1) % n][1])
        high = y > below_y
        if left:                      # il ne faut pas encore y dans S
            if S[rank]:
                return False          # inters. entre deux segm. horiz.
            S[rank] = -1              # ajouter y à S
        else:
            S[rank] = 0               # enlever y de S
        if high:
            lo = y_to_rank[below_y]   # vérifier S entre lo + 1 et rank - 1
            if (below_y != last_y or last_y == y or
                rank - lo >= 2 and S.range_min(lo + 1, rank)):
                return False          # inters. entre segm. horiz. et vertic.
        last_y = y                    # mémoriser pour prochaine itération
    return True
Exemplo n.º 4
0
    def __init__(self, graph):
        """builds the structure from a given tree

        :param graph: adjacency matrix of a tree
        :complexity: O(n log n), with n = len(graph)
        """
        n = len(graph)
        dfs_trace = []
        self.last = [None] * n
        to_visit = [(0, 0, None)]            # sommet 0 est la racine
        next = [0] * n
        while to_visit:
            level, node, father = to_visit[-1]
            self.last[node] = len(dfs_trace)
            dfs_trace.append((level, node))
            if next[node] < len(graph[node]) and \
               graph[node][next[node]] == father:
                next[node] += 1
            if next[node] == len(graph[node]):
                to_visit.pop()
            else:
                neighbor = graph[node][next[node]]
                next[node] += 1
                to_visit.append((level + 1, neighbor, node))
        self.rmq = RangeMinQuery(dfs_trace, (float('inf'), None))
Exemplo n.º 5
0
def is_simple(polygon):
    """Test if a rectilinear polygon is is_simple

    :param polygon: list of points as (x,y) pairs along the closed polygon
    :returns: True if the segements do not intersect
    :complexity: O(n log n) for n=len(polygon)
    """
    n = len(polygon)
    order = list(range(n))
    order.sort(key=lambda i: polygon[i])  # lexicographic order
    rank_to_y = list(set(p[1] for p in polygon))
    rank_to_y.sort()
    y_to_rank = {y: rank for rank, y in enumerate(rank_to_y)}
    S = RangeMinQuery([0] * len(rank_to_y))  # sweep structure
    last_y = None
    for i in order:
        x, y = polygon[i]
        rank = y_to_rank[y]
        #                             -- type of point
        right_x = max(polygon[i - 1][0], polygon[(i + 1) % n][0])
        left = x < right_x
        below_y = min(polygon[i - 1][1], polygon[(i + 1) % n][1])
        high = y > below_y
        if left:  # y does not need to be in S yet
            if S[rank]:
                return False  # two horizontal segments intersect
            S[rank] = -1  # add y to S
        else:
            S[rank] = 0  # remove y from S
        if high:
            lo = y_to_rank[below_y]  # check S between [lo + 1, rank - 1]
            if (below_y != last_y or last_y == y
                    or rank - lo >= 2 and S.range_min(lo + 1, rank)):
                return False  # horiz. & vert. segments intersect
        last_y = y  # remember for next iteration
    return True
class LowestCommonAncestorRMQ:
    """Lowest common ancestor data structure using a reduction to
       range minimum query
    """
    def __init__(self, graph):
        """builds the structure from a given tree

        :param graph: adjacency matrix of a tree
        :complexity: O(n log n), with n = len(graph)
        """
        n = len(graph)
        dfs_trace = []
        self.last = [None] * n
        to_visit = [(0, 0, None)]  # sommet 0 est la racine
        next = [0] * n
        while to_visit:
            level, node, father = to_visit[-1]
            self.last[node] = len(dfs_trace)
            dfs_trace.append((level, node))
            if next[node] < len(graph[node]) and \
               graph[node][next[node]] == father:
                next[node] += 1
            if next[node] == len(graph[node]):
                to_visit.pop()
            else:
                neighbor = graph[node][next[node]]
                next[node] += 1
                to_visit.append((level + 1, neighbor, node))
        self.rmq = RangeMinQuery(dfs_trace, (float('inf'), None))

    def query(self, u, v):
        """:returns: the lowest common ancestor of u and v
        :complexity: O(log n)
        """
        lu = self.last[u]
        lv = self.last[v]
        if lu > lv:
            lu, lv = lv, lu
        return self.rmq.range_min(lu, lv + 1)[1]
Exemplo n.º 7
0
class LowestCommonAncestorRMQ:
    """Lowest common ancestor data structure using a reduction to
       range minimum query
    """
    def __init__(self, graph):
        """builds the structure from a given tree

        :param graph: adjacency matrix of a tree
        :complexity: O(n log n), with n = len(graph)
        """
        n = len(graph)
        dfs_trace = []
        self.last = [None] * n
        to_visit = [(0, 0, None)]            # sommet 0 est la racine
        next = [0] * n
        while to_visit:
            level, node, father = to_visit[-1]
            self.last[node] = len(dfs_trace)
            dfs_trace.append((level, node))
            if next[node] < len(graph[node]) and \
               graph[node][next[node]] == father:
                next[node] += 1
            if next[node] == len(graph[node]):
                to_visit.pop()
            else:
                neighbor = graph[node][next[node]]
                next[node] += 1
                to_visit.append((level + 1, neighbor, node))
        self.rmq = RangeMinQuery(dfs_trace, (float('inf'), None))

    def query(self, u, v):
        """:returns: the lowest common ancestor of u and v
        :complexity: O(log n)
        """
        lu = self.last[u]
        lv = self.last[v]
        if lu > lv:
            lu, lv = lv, lu
        return self.rmq.range_min(lu, lv + 1)[1]