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

确定比赛名次

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

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;
public class P1285 {
	static Scanner sc;
	static int n; 
    static int m;
    static int arc[][];//拓扑图---每个节点之间是否有弧 n*n
	static int sorted[];//每个节点颜色:已排序或未排序
	static int degree[];//每个节点的入度	
	public static void main(String[] args) {
		sc=new Scanner(System.in);
		while(sc.hasNext()){
		n=sc.nextInt(); 
		m=sc.nextInt();
		init();//输入并初始化图
		topoSort();//拓扑排序并输出
		}
	}
	private static void topoSort() {
		int s=0;//表示已经排序的节点个数
		
while(s<n){
			/*按顺序遍历所有节点,若发现入度为0且未排序的,
			 * 即中止本次遍历,对其(当前节点i)进行排序:
			 * 出栈,标记已排,且把它的下级节点入度减1。
			 */
	         int i=0;
	         for(;i<n;i++){
	        	 if(degree[i]==0 && sorted[i]==0){
	        		  break;
	        	 }
	         }
	         
	         if(i==n){
	        	 System.out.println("图中存在回路,无解!");
					return;
	         }
	         
	        //节点i即是刚刚出栈的节点
	        sorted[i]=1;//标记为已排序
	    	//消去i所发出的边---即让对方的入度减1
	        for(int j=0;j<n;j++){
				if(arc[i][j]==1){
					degree[j]--;
				}
			}
	        
	        s++;
	        if(s<n){
				System.out.print(i+1+" ");
			}else{
				System.out.println(i+1);
			}
          }
	}
	//输入并初始化图
	private static void init() {
		sorted=new int[n];//0未排序,1为已排序
		degree=new int[n];
		arc=new int[n][n];//图--用矩阵存储
		
		//读取m场比赛结果,把它记录为图中的弧,并转化为输比赛节点的入度
		for(int j=0;j<m;j++){
			int a=sc.nextInt()-1;
			int b=sc.nextInt()-1;
			if(arc[a][b]==0){ //防止重边
				arc[a][b]=1;
				degree[b]++;	
			}
		}
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值