rt,过了讨论区里找到的所有hack,还是只有10pts
做法是 y 向 x 连有向边,先跑一遍dfs求出每个点能到达的编号最小的点 mn[u],然后因为是 vector 存图,所以直接对每个vector排序,第一关键字是 mn[x],第二关键字 x,然后再来一遍dfs记录答案。
感觉真没啥问题了啊,求教/kel
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pb push_back
const ll N=114514,M=1919810;
ll T;
ll n,m;
vector <ll> g[N],out;
bool vis[N],vi[N],flag;
ll mn[N];
void dfs1(ll u){
if(flag) return;
vi[u]=1,mn[u]=u;
for(int v:g[u]){
//cout<<"? "<<u<<" "<<v<<'\n';
if(vis[v]) continue;
if(vi[v]){
flag=1;
return;
}
dfs1(v);
mn[u]=min(mn[u],mn[v]);
}
vis[u]=1;
}
bool cmp(ll x,ll y){
return mn[x]^mn[y]?mn[x]<mn[y]:x<y;
}
void dfs(ll u){
for(int v:g[u]){
if(vis[v]) continue;
dfs(v);
}
out.pb(u),vis[u]=1;
}
void solve(){
cin>>n>>m;
flag=0,out.clear();
for(int i=1;i<=n;++i) g[i].clear(),vis[i]=vi[i]=0;
for(int i=1;i<=m;++i){
ll a,b;
cin>>a>>b;
g[b].pb(a);
}
for(int i=1;i<=n;++i)
if(!vis[i]){
dfs1(i);
if(flag){
cout<<"Impossible!\n";
return;
}
}
for(int i=1;i<=n;++i) sort(g[i].begin(),g[i].end(),cmp),vis[i]=0;
for(int i=1;i<=n;++i)
if(!vis[i]) dfs(i);
for(int i:out) cout<<i<<" ";cout<<'\n';
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>T;
while(T--) solve();
return 0;
}