拓扑排序

目录

前言:

HDU 1285 确定比赛名次


前言:

https://blog.csdn.net/simon_coder/article/details/51557905

HDU 1285 确定比赛名次

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   |   We have carefully selected several similar problems for you:  1233 2647 1232 3342 1811 

拓扑排序是在学习数据结构的时候接触的,虽然现在依稀还记得理论,但是从未用代码实现过,所以现在用代码实现拓扑排序过程,参考了很多博客与书籍,拓扑排序的知识还是要加强。今日神烦,不再多写。

https://blog.csdn.net/u012860063/article/details/38018811 

拓扑排序+优先队列:

题意:给定两个数字的先后次序,让我们将这个元素合并到一起并且按照从小到大排序。

解析:

我们给定的每两个元素看成节点1 2 的意思就是节点1指向节点2,1——>2 ,代表1排在2前面,根据题目给的样例,我们就可以画出一个图。

 

 我们就可以根据这个图,来解这个题目。

凡是没有入度的节点,就是没有比这个节点排名更靠前的点了,例如上图的:1 4 

所以1和4的排名就可以确定了,根据题目要求

输出时编号小的队伍在前

就把1排好了(1在最前面),把1去掉之后,入度为0的就剩下2 和4,还是取最小的,就是2,

1和2去掉之后,入度为0的就剩下了4,再把4去掉,最后剩下的就是最小的了。

 这个过程就是拓扑排序的过程,也是题目要求我们输出排名的要求。

 拓扑排序有多个序列,我们要其中一种情况。

 

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
int map[520][520];
int vis[520];
int n,m;
priority_queue<int,vector<int>,greater<int> >Q;//越小的整数优先级越大
void topo()
{
	for(int i=1;i<=n;i++)
	{
		if(vis[i]==0)//从入度为0的点开始,压入队列
		 Q.push(i);
	}
	int cnt=1;
	while(!Q.empty())
	{
		int v=Q.top();//优先队列里面存放的点从小到大,小的优先 ,取队头
		Q.pop();
		if(cnt!=n)
		{
			cout<<v<<" ";
			cnt++;
		}
		else
		{
			cout<<v<<endl;
		}
		for(int i=1;i<=n;i++)//寻找以点v为起点,与点v相连的点
		{
			if(!map[v][i])
			{
				continue;
			}
			vis[i]--;//因为v点已经输出了,i点的入度减少。
			if(!vis[i])  //入度为0的点,优先入队列 
			Q.push(i);
		}
	}
}
int main()
{
   while(scanf("%d%d",&n,&m)!=EOF)
   {
        int u,v;
     memset(map,0,sizeof(map));
     memset(vis,0,sizeof(vis));
     for(int i=0;i<m;i++)
     {
   	   scanf("%d%d",&u,&v);
   	    if(map[u][v])
   	     continue;
   	    map[u][v]=1;
   	    vis[v]++;//记录j点入度个数,拓扑就是要从入度为0的点开始 
			//printf("in[%d]=%d\n",j,in[j]);
     }
      topo();	
   } 
   return 0;
}

注意:

1.题目要求多组输入。认真读题

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值