BZOJ2535: [Noi2010]Plane 航空管制2(拓撲排序 貪心)

自為風月馬前卒發表於2018-10-19

題意

題目連結

Sol

非常妙的一道題。

首先不難想到拓撲排序,但是直接對原圖按(k)從小到大拓撲排序是錯的。因為當前的(k)大並不意味著後面的點(k)也大

但是在反圖上按(k)從大到小拓撲排序就是對的。為什麼呢?因為題目中給出的條件是下限, 而在反圖上拓撲排序就相當於卡著下限做,因此一定是最優的

對於第二問,同樣在反圖上搞。對每個點分開做,貪心的策略是:如果有其他的飛機可以起飛則讓他們起飛,直到沒有飛機可以起飛,這時的時間就是答案

// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP(x, y) make_pair(x, y)
#define fi first
#define se second
using namespace std;
const int MAXN = 2e5 + 10;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < `0` || c > `9`) {if(c == `-`) f = -1; c = getchar();}
    while(c >= `0` && c <= `9`) x = x * 10 + c - `0`, c = getchar();
    return x * f;
}
int N, M, a[MAXN], inder[MAXN], tmp[MAXN], ans[MAXN];
vector<int> v[MAXN];
void Topsort() {
    priority_queue<Pair> q;
    for(int i = 1; i <= N; i++) 
        if(!inder[i]) q.push(MP(a[i], i));
    int tot = 0;
    while(!q.empty()) {
        int p = q.top().se; q.pop(); ans[++tot] = p;
        for(int i = 0, to; i < v[p].size(); i++) {
            to = v[p][i];
            inder[to]--;
            if(!inder[to]) q.push(MP(a[to], to));
        }
    }
    for(int i = tot; i >= 1; i--) printf("%d ", ans[i]); puts("");
}
int solve(int x) {
    memcpy(inder, tmp, sizeof(tmp));
    priority_queue<Pair> q;
    inder[x] = N;
    for(int i = 1; i <= N; i++) if(!inder[i]) q.push(MP(a[i], i));
    int tim = N; 
    for(int i = N; i; i--) {
        if(q.empty() || (q.top().fi < i)) return i;
        int p = q.top().se; q.pop(); 
        for(int i = 0, to; i < v[p].size(); i++) {
            to = v[p][i];
            inder[to]--;
            if(!inder[to]) q.push(MP(a[to], to));
        }
    }
    return tim;
}
int main() {
    N = read(); M = read();
    for(int i = 1; i <= N; i++) a[i] = read();
    for(int i = 1; i <= M; i++) {
        int x = read(), y = read();
        v[y].push_back(x); inder[x]++; tmp[x]++;
    }
    Topsort();
    for(int i = 1; i <= N; i++) printf("%d ", solve(i));
    return 0;
}
/*
10 10
4 4 3 6 9 9 10 7 10 7
2 9
3 5
6 7
1 5
7 9
10 2
3 8
8 6
3 10
8 5


*/

相關文章