听说原本是紫题
需要先做 i i i 再做 j j j 的限制很自然的让人想到了拓扑排序,然而让编号较小的菜肴尽可能较早输出并不是要求得到最小字典序的答案!! 反面样例可见第三组输入数据,若按最小字典序为 14352 14352 14352 ,使得 2 2 2 号菜肴更迟了。
容易判断当存在环时无解,可以通过跑程序的过程中记录访问过的点的数目,若点数不为 n n n ,则说明存在无法被加入的点。
既然正向不行,那么可以考虑通过反向拓扑进行操作,以最后才能够被操作的作为起始点,原先在正向需要选出最小的,那么反向就是不断找出最大的,可以采用优先队列实现这一点,最后进行逆向输出即可。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
vector <int> h[N];
vector <int> ans;
int in[N];
void solve(){
int n,m,x,y;
cin>>n>>m;
for(int i=1;i<=n;i++){
h[i].clear();
in[i]=0;
}
ans.clear();
priority_queue <int> q;
for(int i=1;i<=m;i++){
cin>>x>>y;
h[y].push_back(x);//反向边
in[x]++;
}
for(int i=1;i<=n;i++)
if(in[i]==0)
q.push(i);//入度为0 入队
int sum=0;//被访问的结点总数
while(!q.empty()){
int temp=q.top();//此时取出的是最后入队的元素
q.pop();
ans.push_back(temp);
sort(h[temp].begin(),h[temp].end());//不了解为什么此处是否排序都是对的(坐等dalao
for(auto a:h[temp]){
in[a]--;
if(in[a]==0)
q.push(a);
}
}
if(ans.size()<n-1){
cout<<"Impossible!"<<endl;
return;
}
for(int i=ans.size()-1;i>=0;i--){
cout<<ans[i]<<" ";
}
cout<<endl;
}
signed main(){
int t;
cin>>t;
while(t--)
solve();
return 0;
}