版权声明:本文为博主原创文章,欢迎转载。如有问题,欢迎指正。 https://blog.csdn.net/weixin_42172261/article/details/87199854
由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
拓扑排序简单说就是对一个有向无环图(DAG)的点进行排序,只有u点是v点的前导或者u点是v点的前导的前导…的前导中的一个,那么u点在v点的前面。
主要思路就是先找到一个没有前导的点输出,然后删掉和这个点和以它为起点的边,然后重复以上操作,直到所有点都输出。
Problem Description
有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。
Input
输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。
Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
Sample Input
4 3
1 2
2 3
4 3
Sample Output
1 2 4 3
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int game[505][505];//有向无环图
int level[505];//各个点的入度
void topological_sort(int n)
{
int i, j, k;
for (i=1; i<=n; i++){//遍历n次 输出n个点
for (j=1; j<=n; j++){
if (level[j]==0){
printf("%d", j);
level[j]=-1;//已输出,标记为-1
k=j;
break;
}
}
for (j=1; j<=n; j++){//删除以这个点为起点的边
if (game[k][j]==1){
game[k][j]=0;
level[j]--;
}
}
if (i!=n) printf(" ");
else printf("\n");
}
}
int main()
{
int n, m;
while (scanf("%d%d", &n, &m)!=EOF){
memset(game, 0, sizeof(game));
memset(level, 0, sizeof(level));
for (int i=1; i<=m; i++){
int u, v;
scanf("%d%d", &u, &v);
if (game[u][v]==0){
game[u][v]=1;//标记两点的方向关系
level[v]++;//v点入度增加
}
}
topological_sort(n);
}
return 0;
}
参考链接:https://blog.csdn.net/qq_38984851/article/details/82844186