码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-03-08 20:15:40      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:

题目:

确定比赛名次

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;
}









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

标签:

原文地址:http://blog.csdn.net/hjd_love_zzt/article/details/44134859

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!