【[HNOI2015]菜肴制作】拓补排序

top-sort 很容易想到这是一道拓补排序的题。但是在安排顺序上很有讲究。看上去有点像字典序尽可能小。但实际上并不能这样。很容易便能举例出反例。但是我们再看,如果数大的尽可能放在后面是有利于我们的,因为我们可以尽可能地将1放在后面考虑(位数考虑先于子典序考虑)。 因此,这道题的做法就是存反图加大根堆拓补排序,让大的数尽可能位数靠后,同时也保证了子典序。
因此,这道题的做法就是存反图加大根堆拓补排序,让大的数尽可能位数靠后,同时也保证了子典序。

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m;
priority_queue<int>q;
int tot,nt[maxn],la[maxn],en[maxn];
int sx[maxn],rd[maxn],nnn;
void dodo()
{
int i,x,y;
for(i=1;i<=n;i++)
{
    if(!rd[i]) q.push(i);
}
while(q.size())
{
    x=q.top();
    sx[nnn--]=x;
    q.pop();
    for(i=la[x];i;i=nt[i])
    {
        if(rd[en[i]]) 
        {
        rd[en[i]]--;
        if(!rd[en[i]]) { q.push(en[i]); }
        }
    }
}
}

int main()
{
int d,i,x,y;
scanf("%d",&d);
while(d--)
{
    memset(nt,0,sizeof(nt)); 
    memset(la,0,sizeof(la));
    memset(nt,0,sizeof(nt));
    memset(rd,0,sizeof(rd));
    memset(sx,0,sizeof(sx));
    tot=0;
    scanf("%d%d",&n,&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        en[++tot]=x; nt[tot]=la[y]; la[y]=tot;//ft
        rd[x]++;
    }
    nnn=n;
    dodo();
    if(nnn==0)
    {
        for(i=1;i<=n;i++) printf("%d ",sx[i]);
    }
    else printf("Impossible!");
    printf("\n");
}
}    

     
posted @ 2018-03-20 23:33  Newuser233  阅读(10)  评论(0编辑  收藏  举报