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
import java.util.Scanner;
/**
* @author YouYuan
* @eMail E-mail:1265161633@qq.com
* @Time 创建时间:2015年8月11日 上午11:39:48
* @Explain 说明:本程序默认从编号小的开始排序,所以得出的解便是最小的在前面
*/
public class 拓扑排序_确定比赛名次 {
static Scanner in = new Scanner(System.in);
static int MAXN = 501;
static int n, m;
static int[][] arc = new int[MAXN][MAXN];// 邻接矩阵,用于储存两个队伍之间的关系
static boolean[] visited = new boolean[MAXN];// 用于存储当前顶点(队伍)是否已经访问过了
static int[] degree = new int[MAXN];// 存储每个顶点的入度数(队伍的前驱数)
public static void main(String[] args) {
while (in.hasNext()) {
n = in.nextInt();
m = in.nextInt();
initialise();
structure();
topologySort();
}
}
/**
* 初始化
*/
private static void initialise() {
for (int i = 0; i < n; i++) {
visited[i] = false;
degree[i] = 0;
for (int j = 0; j < n; j++) {
arc[i][j] = 0;
}
}
}
/**
* 拓扑排序并输出结果
*/
private static void topologySort() {
int sum = 0;//已经排序的顶点数
while(sum < n) {
int i;//存储入度为0的顶点的下标
for (i = 0; i < n; i++) {//查找入度为0并且没有访问过的顶点,即图的起点(排名最靠前的)
if (degree[i]==0 && !visited[i]) {
break;
}
}
if (i == n) {//若i==n,说明当前图中无入度为0的顶点,是一个回路
System.out.println("图中有回路,无解");
return;
}
visited[i] = true;//标记当前顶点已访问
System.out.print(i+1);//输出编号
sum++;
System.out.print(sum < n ? " " : "");
for (int j = 0; j < n; j++) {
if (arc[i][j] == 1) {
degree[j]--;//以当前排序了的顶点为前驱的顶点的入度-1
}
}
}
System.out.println();
}
/**
* 构造图
*/
private static void structure() {
while (--m >= 0) {
int a = in.nextInt() - 1;
int b = in.nextInt() - 1;
if (arc[a][b] == 0) {//去除重复数据
arc[a][b] = 1;
degree[b]++;
}
}
}
}