[HNOI2015]菜肴制作
題目描述
知名美食家小 A被邀請至ATM 大酒店,為其品評菜肴。 ATM 酒店為小 A 準備了 N 道菜肴,酒店按照為菜肴預估的質量從高到低給予1到N的順序編號,預估質量最高的菜肴編號為1。
由於菜肴之間口味搭配的問題,某些菜肴必須在另一些菜肴之前制作,具體的,一共有 M 條形如”i 號菜肴‘必須‘先於 j 號菜肴制作“的限制,我們將這樣的限制簡寫為<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!“表示無解(不含引號)。
輸入輸出樣例
輸入樣例#1:3 5 4 5 4 5 3 4 2 3 2 3 3 1 2 2 3 3 1 5 2 5 2 4 3輸出樣例#1:
1 5 3 4 2 Impossible! 1 5 2 4 3
說明
【樣例解釋】
第二組數據同時要求菜肴1先於菜肴2制作,菜肴2先於菜肴3制作,菜肴3先於
菜肴1制作,而這是無論如何也不可能滿足的,從而導致無解。
100%的數據滿足N,M<=100000,D<=3。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[200001]; 11 int num,head[200001],du[200001],n,m,a[200001],ans[200001],tot,cnt; 12 int vis[200001]; 13 priority_queue<int>q; 14 int Q[200001]={0}; 15 int gi() 16 {int x=0; 17 char ch=getchar(); 18 while (ch<‘0‘||ch>‘9‘) ch=getchar(); 19 while (ch>=‘0‘&&ch<=‘9‘) 20 { 21 x=(x<<1)+(x<<3)+ch-‘0‘; 22 ch=getchar(); 23 } 24 return x; 25 } 26 void add(int u,int v) 27 { 28 num++; 29 edge[num].next=head[u]; 30 head[u]=num; 31 edge[num].to=v; 32 } 33 bool pd() 34 {int i,u,v; 35 while (q.empty()==0) q.pop(); 36 for (i=1;i<=n;i++) 37 if (du[i]==0) q.push(i); 38 while (q.empty()==0) 39 { 40 u=q.top(); 41 q.pop(); 42 for (i=head[u];i;i=edge[i].next) 43 { 44 v=edge[i].to; 45 du[v]--; 46 if (du[v]==0) 47 { 48 q.push(v); 49 } 50 } 51 } 52 for (i=0;i<=n;i++) 53 if (du[i]) return 0; 54 return 1; 55 } 56 void topsort(int x) 57 {int i,u,v; 58 while (!q.empty()) q.pop(); 59 q.push(x); 60 while (q.empty()==0) 61 { 62 u=q.top(); 63 q.pop(); 64 a[++tot]=u; 65 for (i=head[u];i;i=edge[i].next) 66 { 67 v=edge[i].to; 68 if (vis[v]!=x) continue; 69 du[v]--; 70 if (du[v]==0) 71 { 72 q.push(v); 73 } 74 } 75 } 76 } 77 void bfs(int x) 78 {int i; 79 vis[x]=x; 80 int h=0,t=1,u,v; 81 Q[1]=x; 82 while (h<t) 83 { 84 h++; 85 u=Q[h]; 86 for (i=head[u];i;i=edge[i].next) 87 { 88 v=edge[i].to; 89 if (vis[v]==0) 90 { 91 t++; 92 Q[t]=v; 93 vis[v]=x; 94 } 95 if (vis[v]==x) du[v]++; 96 } 97 } 98 } 99 int main() 100 {int T,i,j,u,v; 101 cin>>T; 102 while (T--) 103 {num=0;cnt=0; 104 memset(head,0,sizeof(head)); 105 memset(vis,0,sizeof(vis)); 106 memset(du,0,sizeof(du)); 107 cin>>n>>m; 108 for (i=1;i<=m;i++) 109 { 110 u=gi();v=gi(); 111 add(v,u); 112 du[u]++; 113 } 114 if (!pd()) 115 { 116 cout<<"Impossible!\n"; 117 } 118 else 119 { 120 memset(vis,0,sizeof(vis)); 121 for (i=1;i<=n;i++) 122 if (vis[i]==0) 123 { 124 tot=0; 125 bfs(i); 126 topsort(i); 127 for (j=tot;j>=1;j--) 128 ans[++cnt]=a[j]; 129 } 130 for (i=1;i<=cnt;i++) 131 printf("%d ",ans[i]); 132 cout<<endl; 133 } 134 } 135 }
[HNOI2015]菜肴制作