(hdu step 5.2.5)确定比赛名次(求拓扑序列)

题目:

确定比赛名次

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 337 Accepted Submission(s): 180
 

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


Author

SmallBeer(CML)


Source

杭电ACM集训队训练赛(VII)


Recommend

lcy

题目分析:

拓扑序列,简单题。

这里面也还有几道拓扑序列的题:http://blog.csdn.net/hjd_love_zzt/article/details/28700653

使用邻接矩阵AC的代码:

/*
 * e1.cpp
 *
 *  Created on: 2015年3月8日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 505;
int map[maxn][maxn];//连接情况.例如map[a][b]=1表示a与b连通
int indegree[maxn];//用于存储各点的入度
int queue[maxn];//最后的拓扑序列

int n;//点数
int m;//边数
int cnt;//拓扑序列中的节点数

/**
 * 求拓扑序列
 */
void topo() {
	int i;
	int j;
	int k;

	for (i = 1; i <= n; ++i) {//枚举所有起点
		for (j = 1; j <= n; ++j) {//枚举所有终点
			if (indegree[j] == 0) {//如果某一终点的入度为0
				indegree[j]--;//移除该点
				queue[cnt++] = j;//将该点加入拓扑序列中

				//将以该点为起点的所有边的终点的入度-1
				for (k = 1; k <= n; ++k) {
					if (map[j][k] != 0) {
						indegree[k]--;
					}
				}

				break;//这个一定要有,否则会wa。break只对本层循环起作用。不对if-esle语句起作用
			}

			//存在环的情况
			if (j > n) {
				cout << "存在环" << endl;
				return;
			}
		}
	}
}

int main() {
	while (scanf("%d%d", &n, &m) != EOF) {
		memset(indegree, 0, sizeof(indegree));
		memset(map, 0, sizeof(map));
		cnt = 0;

		int i;
		for (i = 0; i < m; ++i) {
			int a, b;
			scanf("%d%d", &a, &b);

			if (map[a][b] == 0) {//去重.这道题可能存在重复数据。例如1 2这组数据出现多次
				map[a][b] = 1;
				indegree[b]++;
			}
		}

		topo();

		for (i = 0; i < cnt - 1; ++i) {
			printf("%d ", queue[i]);
		}
		printf("%d\n", queue[cnt - 1]);
	}

	return 0;
}

使用链式前向星实现的拓扑排序,不过输出的顺序不符合这道题的题意,但是大家可以借此学一下

链式前向星的写法:

/*
 * e.cpp
 *
 *  Created on: 2015年3月8日
 *      Author: Administrator
 */

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 501;
const int maxm = maxn * maxn;

struct edge {
	int to;
	int weight;
	int next;
} edge[maxm];
int head[maxn];
int indegree[maxn];

int n, m;

void topo() {
	int queue[maxn];
	int iq = 0;

	int i;
	for (i = 1; i <= n; ++i) {
		if (indegree[i] == 0) {
			queue[iq++] = i;
		}
	}

	for (i = 0; i < iq; ++i) {
		int k;
		for (k = head[queue[i]]; k != -1; k = edge[k].next) {
			indegree[edge[k].to]--;
			if (indegree[edge[k].to] == 0) {
				queue[iq++] = edge[k].to;
			}
		}
	}

	for(i = 0 ; i <= iq-2 ; ++i){
		printf("%d ",queue[i]);
	}
	printf("%d\n",queue[iq-1]);

//	if (iq < n) { //如果iq的最终值小于n.说明拓扑序列不存在...
//		printf("T_T\n");
//		printf("%d\n", n - iq);
//	} else {
//		printf("o(∩_∩)o\n");
//	}

}

int main() {
	while (scanf("%d%d", &n, &m) != EOF) {
		memset(head, -1, sizeof(head));
		memset(indegree, 0, sizeof(indegree));

		int cnt = 0;

		int i;
		for (i = 1; i <= m; ++i) {
			int a;
			int b;
			scanf("%d%d", &a, &b);

			indegree[b]++;
			edge[cnt].to = b;
			edge[cnt].next = head[a];
			head[a] = cnt++;
		}

		topo();
	}

	return 0;
}
时间: 2024-10-12 10:14:55

(hdu step 5.2.5)确定比赛名次(求拓扑序列)的相关文章

(hdu step 5.2.6)确定比赛名次(求入度为0的点的个数)

题目: 确定比赛名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 338 Accepted Submission(s): 181   Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得

[ACM] hdu 1285 确定比赛名次 (拓扑排序)

确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10358    Accepted Submission(s): 4046 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直

HDU 1285 确定比赛名次(拓扑排序+优先队列)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输入有若干组,每组中的第一行为二个数N(1<=N<

HDU 1285 确定比赛名次(拓扑排序模板)

题意还是比较容易理解的,关键要看到后面的:合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前: 思路:这道题就是拓扑排序的经典应用了,用队列做的考虑优先编号小的出队就可以了. 拓扑排序: 拓扑排序是对有向无回路图(DAG)顶点的一种排序,它使得如果存在从u到v的有向路径,那么满足序列中u在v前. 所以我们的算法可以描述为这样一个过程: 1.找到整个图中所有的度为0的点,将这些点压进队列(栈)中 2.从队列(栈)中取出一点,输出,将该点及它的边删除,找到它所指向的点,如果改点是一个原点(删

HDU 1285——确定比赛名次(拓扑排序入门)

确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 12182    Accepted Submission(s): 4861 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直

hdoj 1085 确定比赛名次 【拓扑排序】

中文题,不解释. 这是我的第一道拓扑排序题,先来讲一下什么是拓扑排序: 拓扑排序其实就是如果要进行某一项活动的时候,它的基础活动要先进行.比如说,学概率论之前必须要学会高等数学,那么高等数学就是学概率论的前提条件,这就牵涉到先后课程怎么学习,就是谁先学谁后学习, 拓扑排序就是解决这类问题的. 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1285 代码: #include<stdio.h> #include<string.h> boo

杭电 1285 确定比赛名次(拓扑排序)

http://acm.hdu.edu.cn/showproblem.php?pid=1285 确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11664    Accepted Submission(s): 4644 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,...

HDU1285 确定比赛名次 【拓扑排序】

确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 11937    Accepted Submission(s): 4753 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直

确定比赛名次 (拓扑排序)

确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 12166    Accepted Submission(s): 4849 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直