题目:确定比赛名次(拓扑排序模板)

版权声明:本文为博主原创文章,欢迎转载。如有问题,欢迎指正。 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

猜你喜欢

转载自blog.csdn.net/weixin_42172261/article/details/87199854