zoukankan      html  css  js  c++  java
  • [国家集训队2011]公交路线 解题报…

    题目:
    Z市交通不发达,所有公交路线覆盖的边竟然一个环也不包含,甚至该市的公交路线有可能会分为几个互不连通的块,这可真是不可思议。有一天,你突然听到一条消息,说你的M个同学被困在了Z市里,他们分别要从他们当前所在的点ai移动到他们想去的点bi.于是你立刻调集资料,了解了Z市的形状和公交路线的分布,现在你要算出每个人到达目的地最少要换多少次车,或者告知那个人不能仅用公交车达到目的地。

    分析:
    先考虑一个询问。假设我们想要从A走到B,像这样:
    [国家集训队2011]公交路线 <wbr>解题报告

    大概的路线是:从A向上走,然后经过LCA(A,B),再向下走。

    对于从A向上走这一部分,如图:
    [国家集训队2011]公交路线 <wbr>解题报告
    很显然,如果没有越过LCA,就可以尽量一直走。就像前两个红箭头一样,坐从此出发的最远一班车向上走。

    但如果在某处,“最远的一班车”越过了LCA,那情况就变得不确定了——它的路线有可能继续向上,也有可能折向下,我们先不去考虑它。能够确定的是,如果“最远一班车”达到的最浅节点仍然是LCA的后代,坐这班车一定是最优解。

    我们对于A和B都执行“在越过LCA之前走最远”的操作。像这样:
    [国家集训队2011]公交路线 <wbr>解题报告
    A花stepA步走到了A',B花stepB步走到了B'。
    答案是多少呢?
    如果有一条线路能从A'到B',那答案就是stepA+stepB(共搭乘了stepA+stepB+1条线路,转车次数就是stepA+stepB次)。
    如果没有A'~B'的线路,那要么无解,要么答案就是stepA+stepB+1(从A'走到LCA,再从LCA走到B')。

    所以答案分成两部分:①对AB执行“越过LCA之前尽量向上走”。②判断A'是否能直接乘车到B'。
    我们来分别讨论这两个模块。

    ①的想法比较显然,用倍增即可。为此对于每个点,需要记录它向上乘1,2,4,8……次车走到的最远点。2,4,8……的情况可以DP出来,关键在于:如何知道从某点出发,向上乘一次车最远走到哪里?

    下面来解决这个问题。设点u向上乘一次车走到的最远点是r[u]。
    首先,由于我们只关心向上走,所以对于一条线路(s,t),可以将其拆成两条线(s,g)和(g,t),其中g=LCA(s,t)。

    得出所有像这样“直上直下”的路径后,我们进行如下处理:
    将所有路径按照较浅点的深度从小到大排序,然后对于每条路径(s,t),从t向上遍历到s,如果某个点的r值为零(初始化的值),就将其设为s,否则就退出。

    如图:
    [国家集训队2011]公交路线 <wbr>解题报告
    假设浅蓝色和红色弧线都代表公交线路,深蓝色直线代表一条“直上直下”的链。
    在这个算法中,浅蓝色弧线显然比红色线早处理到,因此在处理红色线时,中间重叠部分的r值已经非零。我们沿着红色线从底向上确定那些顶点的r值,在处理到重叠部分时就会跳出。

    这样,扫描的复杂度就是O(N),因为每个顶点的r值只会被赋值一次,并额外访问一次。

    计算出r值之后就可以用倍增解决问题①。

    下面来看问题②:
    问题②等价于:是否有一条公交线路(s,t),其起点s在A'的子树内,终点t在B'的子树内(或相反,s在B'子树内而t在A'子树内)。

    即:是否有一条公交线路(s,t),满足dfn[A']<=dfn[s]<=last[A']且dfn[B']<=dfn[t]<=last[B'](或相反)。
    其中dfn[x]代表x节点在DFS时首次被遍历到的时间,last[x]代表x节点最后一次被遍历到的时间,显然夹在二者之间的那些节点就是x的子树。

    把这两个限制改写一下:在x坐标范围dfn[A']~last[A'],y坐标范围dfn[B']~last[B']的矩形中,是否存在某个点(dfn[s],dfn[t])或(dfn[t],dfn[s])。

    也就是:给定一堆点和一堆矩形,问每个矩形内包含了多少点。(其实只需要判断有没有)

    这是一个经典的问题。建立一棵线段树(其实树状数组就行了),用水平扫描线从上向下扫描,每扫到一个点就在线段树相应位置++,每遇到矩形上/下边界就记录下来当前的值,那么每个矩形内的点数就是下边界的值减去上边界的值。

    这就解决了。当然,这道题写起来还是比较烦人的……

    代码:
  • 相关阅读:
    poj 2676 Suduku (dfs)
    poj 1562 Oil Deposits (dfs)
    poj 2907 Collecting Beepers (dfs)
    poj 1655 Balancing Act (树形dfs)
    poj 3411 Paid Roads (dfs)
    hdu 2896 病毒侵袭 (AC)
    hdu 3065 病毒侵袭持续中 (AC)
    poj 2251 Dungeon Master (bfs)
    java中debug使用
    Swing入门级小项目总结
  • 原文地址:https://www.cnblogs.com/wmdcstdio/p/7554263.html
Copyright © 2011-2022 走看看