题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4857
先上几个知识点的讲解
https://blog.csdn.net/qq_35644234/article/details/60578189 拓扑排序
https://blog.csdn.net/galesaur_wcy/article/details/75299979 优先队列
https://blog.csdn.net/wxq1987525/article/details/6573542 vector,list,map,queue,deque的区别
很经典的拓扑排序的模板题,先寻找最后一个人(入度为0),然后删除这个点和它关联的边,然后再寻找下一个入度为0的点......
注意 这个题用cin输入会TLE!!!!
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define MAX 30050
using namespace std;
vector<int>edge[MAX];
priority_queue<int> q;
int in[MAX];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m,a,b,i,j;
memset(in,0,sizeof(in));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
edge[i].clear();
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);//题意a必须在b前面
in[a]++;
edge[b].push_back(a);
}
for(i=1;i<=n;i++)
{
if(!in[i]) q.push(i);//找最后一个人
}
vector<int>ans;
while(!q.empty())
{
int u=q.top();
ans.push_back(u);//每一个入度为0的元素都存在容器ans里
q.pop();
for(i=0;i<edge[u].size();i++)
{
int v=edge[u][i];//v赋值为出队的前继元素
in[v]--;
if(in[v]==0) q.push(v);//q本身是优先队列,若有多个入度为0的点,会自动降序排序
}
}
for(i=ans.size()-1;i>=0;i--)//逆序输出
{
if(i!=0)cout<<ans[i]<<" ";
else printf("%d\n",ans[i]);
}
}
return 0;
}