P3243 HNOI2015 菜餚製作 拓撲排序

2022-04-07 21:54:44 字數 2309 閱讀 5647

知名美食家小 a被邀請至atm 大酒店,為其品評菜餚。 atm 酒店為小 a 準備了 n 道菜餚,酒店按照為菜餚預估的質量從高到低給予1到n的順序編號,預估質量最高的菜餚編號為1。

由於菜餚之間口味搭配的問題,某些菜餚必須在另一些菜餚之前製作,具體的,一共有 m 條形如」i 號菜餚'必須'先於 j 號菜餚製作「的限制,我們將這樣的限制簡寫為。

現在,酒店希望能求出乙個最優的菜餚的製作順序,使得小 a能盡量先吃到質量高的菜餚:

也就是說,

(1)在滿足所有限制的前提下,1 號菜餚」盡量「優先製作;

(2)在滿足所有限制,1號菜餚」盡量「優先製作的前提下,2號菜餚」盡量「優先製作;

(3)在滿足所有限制,1號和2號菜餚」盡量「優先的前提下,3號菜餚」盡量「優先製作

;(4)在滿足所有限制,1 號和 2 號和 3 號菜餚」盡量「優先的前提下,4 號菜餚」盡量「優先製作;

(5)以此類推。

例1:共4 道菜餚,兩條限制<3,1>、<4,1>,那麼製作順序是 3,4,1,2。

例2:共5道菜餚,兩條限制<5,2>、 <4,3>,那麼製作順序是 1,5,2,4,3。

例1裡,首先考慮 1,因為有限制<3,1>和<4,1>,所以只有製作完 3 和 4 後才能製作 1,而根據(3),3 號又應」盡量「比 4 號優先,所以當前可確定前三道菜的製作順序是 3,4,1;接下來考慮2,確定最終的製作順序是 3,4,1,2。

例 2裡,首先製作 1是不違背限制的;接下來考慮 2 時有<5,2>的限制,所以接下來先製作 5 再製作 2;接下來考慮 3 時有<4,3>的限制,所以接下來先製作 4再製作 3,從而最終的順序是 1,5,2,4,3。 現在你需要求出這個最優的菜餚製作順序。無解輸出」impossible!「 (不含引號,首字母大寫,其餘字母小寫)

第一行是乙個正整數d,表示資料組數。 接下來是d組資料。 對於每組資料: 第一行兩個用空格分開的正整數n和m,分別表示菜餚數目和製作順序限制的條目數。 接下來m行,每行兩個正整數x,y,表示」x號菜餚必須先於y號菜餚製作「的限制。(注意:m條限制中可能存在完全相同的限制)

輸出檔案僅包含 d 行,每行 n 個整數,表示最優的菜餚製作順序,或者「impossible!「表示無解(不含引號)。

輸入

354

5453

4232

3312

2331

5252

43

輸出

153

42impossible! 15

243

【樣例解釋】

第二組資料同時要求菜餚1先於菜餚2製作,菜餚2先於菜餚3製作,菜餚3先於

菜餚1製作,而這是無論如何也不可能滿足的,從而導致無解。

100%的資料滿足n,m<=100000,d<=3。

題解:

①impossible的情況:當且僅當出現閉環時。

②設編號小的菜為,編號大的菜為b。我們想要a盡量往前靠,貪心很容易舉出反例

如:4種菜餚,限制為<2,4><3,1>,

那麼字典序最小的是2,3,1,4,但題目要求的最優解是3,1,2,4。

③如果最後乙個數字在合法範圍內盡可能大,那麼這樣是絕對有利的。

因為如果設最後乙個數字是x,那麼除了x之外的所有數都不會被放到最後乙個位置。

因此,最優解就是符合條件的排列中,反序列的字典序最大的排列。

反向跑拓撲。讓b連向a,跑反圖的拓撲。利用優先佇列維護。

#include#include

#include

#include

#include

#include

using

namespace

std;

const

int n = 1e5 + 5

;int

n, m, cnt, t, indeg[n], ans[n];

vector

edge[n];

void

input()

}void

topsort()

for(int i = 0;i < edge[tmp].size();i ++)

}}void

output()

for(int i = n; i ;i --) cout << ans[i] << "

"; cout <}void

clear()

intmain()

題解 P3243 HNOI2015 菜餚製作

這道題看起來就是個裸的拓撲排序,抄上模板就能ac。上面這種想法一看就不現實,然鵝我第一次還真就這麼寫了,然後被隨意hack。我們需要注意一句話 現在,酒店希望能求出乙個最優的菜餚的製作順序,使得小 a能盡量先吃到質量高的菜餚 這句話什麼意思呢?看上去它是說想要乙個字典序最小的排列,但我們可以發現,題...

洛谷P3243 HNOI2015 菜餚製作

題目 菜餚製作 思路 拓撲排序 注意這裡不是輸出字典序最小的方案。讀入時反向連邊,對這張反圖拓撲排序時要把佇列改為優先佇列,再反向輸出結果。includeusing namespace std define maxn 100000 int n,m vectorg maxn 5 int du maxn...

洛谷P3243 HNOI2015 菜餚製作

題目傳送門 這道題看上去就知道是拓撲排序,再一看題,應該是求字典序最小的合法方案,所以貪心的找當前入度為0的編號最小的點就行了。恭喜,你掉到坑里了。其實我一開始就是這麼做的,後來在測樣例第三組資料的時候炸掉了,這組資料就可以卡掉這個貪心 這樣例還真良心啊 我們不妨反著考慮,最後一位放合法的最大值 設...