九度OJ-1449:确定比赛名次

  这道题是拓扑排序的第一种应用:利用拓扑排序确定拓扑序列。

题目描述:

有N个比赛队(1<=N<=500),编号依次为1,2,3,。。。。,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。

输入:

输入有若干组,每组中的第一行为二个数N(1<=N<=500),M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。

输出:

给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。

样例输入:
4 3
1 2
2 3
4 3
样例输出:
1 2 4 3
//适用条件:题目给的这张图只能有一个(弱)连通分量(但不要求强连通) 
#include <iostream>
#include <vector>
#include <queue>
#define MAXSIZE 600
using namespace std;

struct Edge{
	int thisNode;
	int nextNode;
	Edge(){
	}
	Edge(int thisNode,int nextNode){
		this->thisNode=thisNode;
		this->nextNode=nextNode;
	}
};
struct Vex{
};
struct Graph{
	int graphSize;
	vector<Edge> edge[MAXSIZE];
//	vector<Vex> vex;
	void initGraph(int graphSize){
		this->graphSize=graphSize;
		for (int i=0;i<graphSize;i++)
			edge[i].clear();
//		vex.clear();
	}
	void addEdge(int thisNode,int nextNode){
		edge[thisNode].push_back(Edge(thisNode,nextNode));
	}
};

int main(){
	int n,m;
	Graph graph;
	int inDegree[MAXSIZE];
	int cnt;
	priority_queue<int,vector<int>,greater<int> > q;
	queue<int> seq;
	int thisNode,nextNode;
	bool firstCase;
	while (cin>>n>>m){
		//initiate
		graph.initGraph(n);
		for (int i=0;i<graph.graphSize;i++)
			inDegree[i]=0;
		while (!q.empty())
			q.pop();
		while (!seq.empty())
			seq.pop();
		cnt=0;
		//input & cal inDegree
		for (int i=0;i<m;i++){
			cin>>thisNode>>nextNode;
			thisNode--;nextNode--;
			graph.addEdge(thisNode,nextNode);
			inDegree[nextNode]++;
		}
		//initiate q
		for (int i=0;i<graph.graphSize;i++){
			if (inDegree[i]==0)
				q.push(i);
		}
		//Topological sorting 
		/*
		使用队列q作为线索,利用了"新出现的入度为0的点必定是由边的删除造成的"这一特性,对顶点进行遍历,较之自己的算法逻辑更优 
		使用了cnt计数器与顶点总数n比较来判定是否顶点皆已删除,较之自己的算法逻辑更优 
		*/
		while(!q.empty()){
			int nowP=q.top();
			seq.push(nowP);//record the seq 
			q.pop();//del the vex
			cnt++;
			for (int i=0;i<graph.edge[nowP].size();i++){//traverse the edges & reduce inDegree
				int nextNode=graph.edge[nowP][i].nextNode;
				inDegree[nextNode]--;
				if (inDegree[nextNode]==0)
					q.push(nextNode);
			}
			graph.edge[nowP].clear();//del the edges
		}
		//output
		firstCase=true;
		while (!seq.empty()){
			if(firstCase==true)
				firstCase=false;
			else
				cout<<' ';
			cout<<seq.front()+1;
			seq.pop();
		}
		cout<<endl;
	}
	return true;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值