BZOJ 2535: [Noi2010]Plane 航空管制2
阿新 • • 發佈:2017-10-14
能力 一行 定義 puts des 超過 可能 枚舉 把他
第一行包含兩個正整數 n和m,n表示航班數目,m表示第二類限制條件(相對起飛順序限制)的數目。 第二行包含 n個正整數 k1, k2, „, kn。 接下來 m行,每行兩個正整數 a和b,表示一對相對起飛順序限制(a, b),其中1≤a,b≤n, 表示航班 a必須先於航班 b起飛。
號,相鄰兩個整數用空格分隔。
4 5 2 5 4
1 2
3 2
5 1
3 4
3 1
3 4 1 2 1
Description
世博期間,上海的航空客運量大大超過了平時,隨之而來的航空管制也頻頻發生。最近,小X就因為航空管制,連續兩次在機場被延誤超過了兩小時。對此,小X表示很不滿意。 在這次來煙臺的路上,小 X不幸又一次碰上了航空管制。於是小 X開始思考關於航空管制的問題。 假設目前被延誤航班共有 n個,編號為 1至n。機場只有一條起飛跑道,所有的航班需按某個順序依次起飛(稱這個順序為起飛序列)。定義一個航班的起飛序號為該航班在起飛序列中的位置,即是第幾個起飛的航班。 起飛序列還存在兩類限制條件: ? 第一類(最晚起飛時間限制):編號為 i的航班起飛序號不得超過 ki; ? 第二類(相對起飛順序限制):存在一些相對起飛順序限制(a, b),表示航班 a的起飛時間必須早於航班 b,即航班 a的起飛序號必須小於航班 b 的起飛序號。 小X 思考的第一個問題是,若給定以上兩類限制條件,是否可以計算出一個可行的起飛序列。第二個問題則是,在考慮兩類限制條件的情況下,如何求出每個航班在所有可行的起飛序列中的最小起飛序號。Input
Output
由兩行組成。
第一行包含 n個整數,表示一個可行的起飛序列,相鄰兩個整數用空格分隔。
輸入數據保證至少存在一個可行的起飛序列。如果存在多個可行的方案,輸出任
意一個即可。
第二行包含 n個整數 t1, t2, „, tn,其中 ti表示航班i可能的最小起飛序
Sample Input
5 54 5 2 5 4
1 2
3 2
5 1
3 4
3 1
Sample Output
3 5 1 4 23 4 1 2 1
題解:
這個題目好難想,首先第一問還是比較套路的,我們對於n個點,連一個反圖,拓撲排序一下,丟到一個按照點權排序的大根堆了面,正確性還是比較顯然的,我們按照拓撲排序的順序,那麽一定滿足了條件二的限制,那麽用堆來搞,他們的點權就是他們的承受能力,那麽承受能力強的排在後面,如果這樣還不行,那麽此題一定無解,(為什麽正著做是錯的我也不知道)。
然後第二問就比較難想了,我們枚舉當前要計算答案的點,那麽考慮拓撲排序的時候不把他丟到堆裏面,直到出現不合法情況的時候,這個時候,就是他最早出現的位置,因為此刻如果還不放他進去,那麽必然序列會不合法,所以這個時刻就是這個點的ans.
代碼:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #include <queue> #define MAXN 200050 #define RG register using namespace std; struct node{ int id,v; bool operator < (const node&x)const{ return x.v>v; } }; struct edge{ int first; int next; int to; int quan; }a[MAXN*2]; priority_queue<node> q; int v[MAXN],in[MAXN],in2[MAXN],ans[MAXN]; int n,m,num=0; void addedge(int from,int to){ a[++num].to=to; a[num].next=a[from].first; a[from].first=num; } inline void work1(){ for(RG int i=1;i<=n;i++) in2[i]=in[i]; for(RG int i=1;i<=n;i++){ if(!in2[i]) q.push((node){i,v[i]}); } while(!q.empty()){ int now=q.top().id;q.pop(); ans[++num]=now; for(RG int i=a[now].first;i;i=a[i].next){ int to=a[i].to; in2[to]--; if(!in2[to]) q.push((node){to,v[to]}); } } } inline int work2(int k){ while(!q.empty()) q.pop(); for(int i=1;i<=n;i++) in2[i]=in[i]; for(int i=1;i<=n;i++){ if(i!=k&&!in2[i]) q.push((node){i,v[i]}); } for(RG int hh=n;hh>=1;hh--){ if(q.empty()||q.top().v<hh) return hh; int now=q.top().id;q.pop(); for(RG int i=a[now].first;i;i=a[i].next){ int to=a[i].to; in2[to]--; if(!in2[to]&&to!=k) q.push((node){to,v[to]}); } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=m;i++){ int x,y;scanf("%d%d",&x,&y); addedge(y,x);in[x]++; } num=0; work1(); for(int i=num;i>=1;i--) printf("%d ",ans[i]);puts(""); for(int i=1;i<=n;i++) printf("%d ",work2(i)); printf("\n"); return 0; }
BZOJ 2535: [Noi2010]Plane 航空管制2