思路:总结题意,在满足某某一定在某某之前的约束条件下,使编号小的尽量靠前。很容易想到用小根堆求拓扑序(然而这是错的),很容易举出反例。正确的思路是求字典序最小的拓扑序,这就需要反向建图,用大根堆求反着的拓扑序。(不要忘记初始化……)
代码:(码风较差,可读性较低)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 100010
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define loop(i,a,b) for(int i=a;i>=b;i--)
#define edge_rep(i,a,b) for(int i=a;i;i=b)
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
struct haha{
int next,to;
}edge[N*3];
bool flag;
int d,n,m,num,cnt,sum;
int indegree[N*3],head[N*3],a[N*3];
priority_queue<int> q;
void add(int x,int y){
edge[++num].to=y;
edge[num].next=head[x];
head[x]=num;
}
int main(){
scanf("%d",&d);
while(d--){
cnt=0;
clr(indegree);clr(a);
clr(edge);clr(head);
while(!q.empty()) q.pop();
scanf("%d%d",&n,&m);
rep(i,1,m){
int u,v;
scanf("%d%d",&u,&v);
add(v,u);//反向建图
indegree[u]++;
}
rep(i,1,n)
if(!indegree[i]){
q.push(i);
}
while(!q.empty()){
int u=q.top();
q.pop();
edge_rep(i,head[u],edge[i].next){
int v=edge[i].to;
indegree[v]--;
if(indegree[v]==0)
q.push(v);
}
a[++cnt]=u;//转存到数组里逆向输出
}
if(cnt==n){
loop(i,cnt,1)
printf("%d ",a[i]);
printf("\n");
}
if(cnt!=n)
printf("Impossible!\n");
}
return 0;
}