題目
題意很簡單,就是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#includeusing namespace std;
int indegree[30200],head[30200],p[30200],n;
struct stu
arr[100200];//不要寫作30200
void topo()
}for(i=n-1;i>=0;i--)//逆序輸出
if(i!=0)
printf("%d ",p[i]);
else
printf("%d\n",p[i]);
}int main()
topo();
}return 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號第二富,以此類推。有錢人就賄賂負責人,所以他們有一些好處。負責人現在可以安排大家排隊的...