zoukankan      html  css  js  c++  java
  • 拓扑编号 vijos1790

    题意就是拓扑排序,要求1的序号尽可能小,然后2的序号尽可能小,3,4...

     

    一开始很容想到直接贪心,每次选一个入度为0的点,如果有多个,就选编号最小的那个,但是很容易找到反例。

    看了下题解,应该是反着做拓扑排序,每次取编号最大的,但是没有人给出证明。下面给出我的证明,欢迎指出错误。

    ps:参考了一位大牛的文章,poj有一道题类似,参考了他的题解,但是找不到了,所以没法放出他的链接了,先道歉。


    假设我们按逆拓扑排序的方法求出了一个拓扑序列(把得到的反序列正过来),记为A。


    假设最优解的拓扑序列是B。


    从后往前比较AB,设在位置k,AB第一次出现不同。即A[k]!=B[k],A[p]=B[p].


    显然根据我们的贪心策略"每次取的是编号最大的",有A[k]>B[k].


    那么我们在B中取寻找A[k],即找到B[p]=A[k].


    然后把B中B[p],B[p+1]...B[k]这一段拿出来,记为序列C。


    因为B[p]=A[k] , 把B[p]换成A[k],C=A[k],B[p+1]....B[k].


    很显然在C中A[k]不是最小的,因为至少B[k]比它小。 假设C中最小的是B[q],那么我们可以构造出一个序列D.


    D=B[p+1],B[p+2]...B[q],A[k],B[q+1]...B[k]. (实质就是把A[k]移到B[q]的后面)


    显然这个序列会比序列C更优,因为B[q]的名次靠前了一名。 那么如果把C换成D会更优,与B是最优解矛盾。


    那么怎么知道序列D一定是合法的呢?因为如果A[k]恰好是B[p+1]的前驱,那么就不能把A[k]移走。


    所以我们回到序列A,序列A中A[k]是AB序列从右往左第一个不同的元素,那么在A中,B[p+1]肯定是在A[k]前面的,所以A[k]不可能是B[p+1]的前驱。


    综上,我们得到的答案就是最优解。 

  • 相关阅读:
    【分享】管理的最高境界是简单
    建立市场化风险评估机制推进地方政府信用评级建设
    手游-神雕侠侣 85侠客纪攻略(已通关)
    使用git的分支功能实现定制功能摘取与组合的想法
    组内正则培训记录
    组内Linq培训记录
    一次代码重构记录
    git代码库误操作还原记录
    关于代码重构的开始
    如何管理高手、大牛?
  • 原文地址:https://www.cnblogs.com/vb4896/p/4083650.html
Copyright © 2011-2022 走看看