1. 程式人生 > >BZOJ 2535: [Noi2010]Plane 航空管制2

BZOJ 2535: [Noi2010]Plane 航空管制2

能力 一行 定義 puts des 超過 可能 枚舉 把他

Description

世博期間,上海的航空客運量大大超過了平時,隨之而來的航空管制也頻頻發生。最近,小X就因為航空管制,連續兩次在機場被延誤超過了兩小時。對此,小X表示很不滿意。 在這次來煙臺的路上,小 X不幸又一次碰上了航空管制。於是小 X開始思考關於航空管制的問題。 假設目前被延誤航班共有 n個,編號為 1至n。機場只有一條起飛跑道,所有的航班需按某個順序依次起飛(稱這個順序為起飛序列)。定義一個航班的起飛序號為該航班在起飛序列中的位置,即是第幾個起飛的航班。 起飛序列還存在兩類限制條件: ? 第一類(最晚起飛時間限制):編號為 i的航班起飛序號不得超過 ki; ? 第二類(相對起飛順序限制):存在一些相對起飛順序限制(a, b),表示航班 a的起飛時間必須早於航班 b,即航班 a的起飛序號必須小於航班 b 的起飛序號。 小X 思考的第一個問題是,若給定以上兩類限制條件,是否可以計算出一個可行的起飛序列。第二個問題則是,在考慮兩類限制條件的情況下,如何求出每個航班在所有可行的起飛序列中的最小起飛序號。

Input

第一行包含兩個正整數 n和m,n表示航班數目,m表示第二類限制條件(相對起飛順序限制)的數目。 第二行包含 n個正整數 k1, k2, „, kn。 接下來 m行,每行兩個正整數 a和b,表示一對相對起飛順序限制(a, b),其中1≤a,b≤n, 表示航班 a必須先於航班 b起飛。

Output

由兩行組成。
第一行包含 n個整數,表示一個可行的起飛序列,相鄰兩個整數用空格分隔。
輸入數據保證至少存在一個可行的起飛序列。如果存在多個可行的方案,輸出任
意一個即可。
第二行包含 n個整數 t1, t2, „, tn,其中 ti表示航班i可能的最小起飛序

號,相鄰兩個整數用空格分隔。

Sample Input

5 5
4 5 2 5 4
1 2
3 2
5 1
3 4
3 1

Sample Output

3 5 1 4 2
3 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