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

题意:给定限制条件(a,b)表示a必须在b之前,求所有合法序列中,小的数尽量在前面的方案

题解:首先我们根据限制条件建反向图,然后在反向图上求字典序最小的拓扑序(队列改为堆),逆序输出即可。

#include <queue>
#include <functional>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;

const int MAXN=100000+2;
struct HASH{
    int u;
    HASH *next;
    HASH(){}
    HASH(int _u,HASH *_next):u(_u),next(_next){}
}*table[MAXN],mem[MAXN*2];
int N,M,Q,cnt,ans[MAXN],degree[MAXN];
priority_queue<int> q;

void Insert(int u,int v){ table[u]=&(mem[cnt++]=HASH(v,table[u]));}

void Topology_Sort(){
    while(!q.empty()) q.pop();

    for(int i=1;i<=N;i++)
        if(!degree[i]) q.push(i);

    while(!q.empty()){
        ans[++cnt]=q.top(),q.pop();
        for(HASH *p=table[ans[cnt]];p;p=p->next){
            degree[p->u]--;
            if(!degree[p->u]) q.push(p->u);
        }
    }
}

int main(){
    scanf("%d",&Q);
    while(Q--){
        memset(table,0,sizeof(table));
        memset(degree,0,sizeof(degree));
        cnt=0;

        scanf("%d %d",&N,&M);
        for(int i=1,u,v;i<=M;i++){
            scanf("%d %d",&u,&v);
            Insert(v,u),degree[u]++;
        }

        cnt=0,Topology_Sort();
        if(cnt!=N) printf("Impossible!\n");
        else{
            for(int i=N;i;i--) printf("%d ",ans[i]);
            printf("\n");
        }
    }

    return 0;
}
View Code

 

posted @ 2017-02-27 22:42  WDZRMPCBIT  阅读(181)  评论(0编辑  收藏  举报