题目传送门
这里正好介绍一下
拓扑排序
先看一下算法思想
- 选择入度为0的点出队 入度:即题中比它强的队伍
- 将与出队的点相连的边去掉
- 重复以上操作,直到所有点都被输出(有环的时候除外) 即题中这句话:"输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。"保证了没有环
- 复杂度只有
参考这幅图看看
看看代码,注释还比较详细~~
#include<bits/stdc++.h>
using namespace std;
const int maxn=510;
bool graph[maxn][maxn];//保存图
int degree[maxn];//保存每个点的入度
int main()
{
freopen("contest.in","r",stdin);
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)//有多组数据
{
memset(graph,0,sizeof(graph));
memset(degree,0,sizeof(degree));
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(!graph[u][v])
{
graph[u][v]=1;
degree[v]++;//v的入度++
}
}
priority_queue<int,vector<int>,greater<int> >q;//小根堆,因为题目要求要从小到大输出
for(int i=1;i<=n;i++)
{
if(degree[i]==0)
q.push(i);
}
bool first=1;
while(!q.empty())
{
int cur=q.top();
q.pop();
if(first)//加入是第一个数
{
cout<<cur;
first=0;
}
else
cout<<" "<<cur;
for(int i=1;i<=n;i++)
{
if(graph[cur][i])//若点i被该入度为零的队伍打败过
{
degree[i]--;//相连的点的入度减1
if(degree[i]==0)//如果入度变为0,即没有比它更强的队伍,就加入队列
q.push(i);
}
}
}
printf("\n");
}
return 0;
}