【[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"); } }