1. 程式人生 > >BZOJ4010 HNOI2015 菜肴制作 貪心、拓撲排序

BZOJ4010 HNOI2015 菜肴制作 貪心、拓撲排序

empty == 字典序 ons n) 需要 efi mat 拓撲排序

傳送門


顯然是拓撲排序

但是並沒有那麽簡單

看起來需要字典序最小,那就拿個堆代替隊列,按照點編號大小拓撲排序,然後你就WA了;還不服輸,按照能夠到達的最小編號的點為第一關鍵字,點的編號為第二關鍵字拓撲排序,結果還是WA了,因為這種貪心只能保證最小的在最前面,不能保證最小的在最前面的前提下次小在最前面……

正著不對,不妨倒著考慮

既然編號小的要盡可能在前面訪問,那麽編號最大的一定要盡可能在最後面。也就是說:最後一個訪問的一定是當前出度為\(0\)的點中出度最大的點,將它去掉之後出度為\(0\)的點中編號最大的點會在第\(N-1\)個訪問……

那麽正確的貪心策略就是:反圖上拓撲排序,貪心地選擇當前入度為\(0\)

的點中編號最大的,這樣就可以得到一個正確的排列了。

#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    bool f = 0;
    while(!isdigit(c)){
        if(c == ‘-‘)
            f = 1;
        c = getchar();
    }
    while(isdigit(c)){
        a = (a << 3) + (a << 1) + (c ^ ‘0‘);
        c = getchar();
    }
    return f ? -a : a;
}

#define PII pair < int , int >
const int MAXN = 1e5 + 7;
struct Edge{
    int end , upEd;
}Ed[MAXN];
int head[MAXN] , in[MAXN] , ans[MAXN];
int N , M , cntEd;
bool vis[MAXN] , ins[MAXN];

inline void addEd(int a , int b){
    Ed[++cntEd].end = b;
    Ed[cntEd].upEd = head[a];
    head[a] = cntEd;
    ++in[b];
}

priority_queue < int > q;
void tSort(){
    for(int i = 1 ; i <= N ; ++i)
        if(!in[i])
            q.push(i);
    int cnt = 0;
    while(!q.empty()){
        int t = q.top();
        q.pop();
        ans[N - cnt++] = t;
        for(int i = head[t] ; i ; i = Ed[i].upEd)
            if(!--in[Ed[i].end])
                q.push(Ed[i].end);
    }
    if(cnt < N)
        puts("Impossible!");
    else{
        for(int i = 1 ; i <= N ; ++i)
            printf("%d " , ans[i]);
        putchar(‘\n‘);
    }
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("in" , "r" , stdin);
    freopen("out" , "w" , stdout);
    #endif
    for(int D = read() ; D ; --D){
        N = read();
        M = read();
        memset(head , 0 , sizeof(head));
        memset(vis , 0 , sizeof(vis));
        memset(in , 0 , sizeof(in));
        cntEd = 0;
        for(int i = 1 ; i <= M ; ++i){
            int a = read() , b = read();
            addEd(b , a);
        }
        tSort();
    }
    return 0;
}

BZOJ4010 HNOI2015 菜肴制作 貪心、拓撲排序