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

浙公网安备 33010602011771号