题目链接:https://www.luogu.com.cn/problem/P3243
因为对于每一个<x,y>,x一定要在y之前做,所以考虑要让y小的在前面,即在合法范围内让后面的y尽可能大,也就是反序列字典序最大的情况。
所以反向建边,跑一边拓扑排序,并用大根堆替换队列(因为要字典序最大)。并且要考虑无解情况:即所求的拓扑序列与总个数n不相等,即无解。
AC代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 #include<cstring> 5 using namespace std; 6 const int N=100005; 7 priority_queue<int> q; 8 int n,m,tot,cnt; 9 struct node{ 10 int to,next; 11 }edge[N]; 12 int head[N],in[N],ans[N]; 13 void init(){ 14 memset(head,-1,sizeof(head)); 15 memset(in,0,sizeof(in)); 16 memset(ans,0,sizeof(ans)); 17 memset(edge,0,sizeof(edge)); 18 tot=cnt=0; 19 while(!q.empty()) q.pop(); 20 } 21 void add(int u,int v){ 22 edge[tot].to=v; 23 edge[tot].next=head[u]; 24 head[u]=tot++; 25 } 26 void toposort(){ 27 for(int i=1;i<=n;i++){ 28 if(in[i]==0) q.push(i); 29 } 30 while(!q.empty()){ 31 int u=q.top();q.pop(); 32 ans[++cnt]=u; 33 for(int i=head[u];i!=-1;i=edge[i].next){ 34 int v=edge[i].to; 35 in[v]--; 36 if(in[v]==0) q.push(v); 37 } 38 } 39 } 40 int main(){ 41 int D; 42 scanf("%d",&D); 43 while(D--){ 44 init(); 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=m;i++){ 47 int x,y; 48 scanf("%d%d",&x,&y); 49 add(y,x); 50 in[x]++; 51 } 52 toposort(); 53 if(cnt!=n) { printf("Impossible! "); continue;} 54 for(int i=n;i>=1;i--) printf("%d ",ans[i]); 55 printf(" "); 56 } 57 return 0; 58 }