题目大意就是:给你一些先后关系,然后输出它们的拓扑序,但是和普通的不一样的地方,输出使编号小的数字尽量靠前的拓扑序,而不一定是字典序。
例如:
4—>2
5—>1—>3
正常情况下字典序最小的拓扑序应该是:4 2 5 1 3
这种规则下,则应该是: 5 1 4 2 3
解法:自己其实是没有想到看题解的QAQ
在当前入度为0的点中,我们先输出哪个并不能完全取决于这个点的大小,而是跟它之后的点尾部有关系。编号小的尽量靠前,其实也是编号大的尽量靠后,我们可以得出结论:大的尾部一定是排在最后的。所以我们可以反向建图,进行拓扑排序,并在优先队列中从大到小排列,每次取编号最大的那个。
#include <bits/stdc++.h>
using namespace std;
const int maxm= 1e5+10;
const int maxn=3e4+10;
int n,m;
int in[maxn];
struct Node{
int to,next;
}node[maxm];
int head[maxn],cnt;
void init()
{
memset(head,-1,sizeof(head));
cnt=0;
memset(in,0,sizeof(in));
}
void add(int u,int v)
{
node[cnt].to=v;
node[cnt].next=head[u];
head[u]=cnt++;
}
int ans[maxn];
void toposort()
{
priority_queue<int > que;
for(int i=1;i<=n;i++)
if(in[i]==0) que.push(i);
int cnt=0;
while(!que.empty())
{
int u=que.top();
que.pop();
ans[cnt++]=u;
// printf("%d%c",u,cnt==n?'\n':' ');
for(int i=head[u];~i;i=node[i].next)
{
int v=node[i].to;
in[v]--;
if(in[v]==0) que.push(v);
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
init();
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(v,u);
in[u]++;
}
toposort();
for(int i=n-1;i>=0;i--)
printf("%d%c",ans[i],i==0?'\n':' ');
}
return 0;
}