首页 > 代码库 > 拓扑编号 vijos1790
拓扑编号 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]的前驱。
综上,我们得到的答案就是最优解。
拓扑编号 vijos1790