題意:n個結點,m個拓撲關係(a,b)表示a必須排在b前面,在滿足m個拓撲關係關係的前提下使得小的結點盡可能的排在前面。也就是說我們現在要從1號結點開始考慮,如果要排1號結點,根據拓撲關係,首先必須排哪些結點,如果排好了1號結點,則繼續考慮2號結點 ,3號結點。。
我們先看兩個例子:
存在拓撲關係:
5 -> 3 -> 1
6 -> 4 -> 2
直接拓撲排序的結果是 5 3 1 6 4 2,結果是正確的(1號盡可能的在前面了) ,看起來好像直接拓撲排序就可以了,但是為什麼提交後卻wa了呢,別急,我們再看乙個例子:
6 -> 3 -> 1
5 -> 4 -> 2
直接拓撲排序的結果是:5 4 2 6 3 1 ,結果是錯誤的,因為我們可以把1號安排到更前面的位置 即:6 3 1 5 4 2(正確答案)。
看到這裡應該就知道為什麼直接拓撲排序不行了吧,我們分析一下為什麼會出現這樣的狀況,對於多條弧或者邊,我們是先刪除弧尾結點比較小的結點即(5號結點比6號結點小,先刪除以該點為尾的弧),而這也正是問題所在,我們希望的是優先刪除弧頭比較小的弧的(1號結點比2號結點小,因優先刪除以1號為頭的弧)。
好了,問題找到了,現在我們在來想如何解決問題,我們可以嘗試一下逆向思維,即我們先考慮哪些點應該靠後釋放,這樣的話我們就可以把拓撲關係反過來(即弧頭和弧尾調換),然後做拓撲排序,然後我們可以根據原來的弧頭(現在變成弧尾)的大小來釋放結點,由於現在的問題變成哪些最後釋放,那麼就應該優先考慮弧尾(原來的弧頭)比較大的,可以通過優先佇列來解決。
#include
#include
#include
#include
#include
using
namespace
std;
const
int maxn = 31000;
pair a[maxn * 4];
int h[maxn];
int in[maxn];
int ans[maxn],cnt;
int main()
else
}priority_queue, less > que;
for(int i=1;i<=n;i++)
if(in[i] == 0) que.push(i);
while( !que.empty())
}for(int i=cnt -1 ;i > 0;i--)
printf("%d ",ans[i]);
printf("%d\n",ans[0]);
}}
HDU 4857 逃生 拓撲排序
time limit 1000ms memory limit 32768kb 64bit io format i64d i64udescription 糟糕的事情發生啦,現在大家都忙著逃命。但是逃命的通道很窄,大家只能排成一行。現在有n個人,從1標號到n。同時有一些奇怪的約束條件,每個都形如 a必須...
HDU 4857 逃生 (拓撲排序)
糟糕的事情發生啦,現在大家都忙著逃命。但是逃命的通道很窄,大家只能排成一行。現在有n個人,從1標號到n。同時有一些奇怪的約束條件,每個都形如 a必須在b之前。同時,社會是不平等的,這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些好處。負責人現在可以安排大家排隊的...
逃生 HDU 4857 拓撲排序
糟糕的事情發生啦,現在大家都忙著逃命。但是逃命的通道很窄,大家只能排成一行。現在有n個人,從1標號到n。同時有一些奇怪的約束條件,每個都形如 a必須在b之前。同時,社會是不平等的,這些人有的窮有的富。1號最富,2號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些好處。負責人現在可以安排大家排隊的...