BZOJ4010 HNOI2015 菜肴制作 贪心、拓扑排序

传送门


显然是拓扑排序

但是并没有那么简单

看起来需要字典序最小,那就拿个堆代替队列,按照点编号大小拓扑排序,然后你就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;
}

猜你喜欢

转载自www.cnblogs.com/Itst/p/10354072.html