hdu 1285 基于入度数排序输出的拓扑排序

内容:

有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

大体思路:

先将所有边进行保存(可以用邻接矩阵或者邻接表或者用vector),题目要求按照字典序输出,所以可以选择用优先队列将所有涉及的顶点保存。

代码:

#include<stdio.h> #include<iostream> #include<string.h> #include<vector> #include<queue> using namespace std; int d[505];//保存要输出的节点 int in[505];//记录每个节点的入度数(每个选手输的次数) int main() { int n,m; vector<int>V[505]; priority_queue<int,vector<int>,greater<int> >Q; while(cin>>n>>m) { for(int i=0;i<505;i++)V[i].clear(); while(!Q.empty())Q.pop(); memset(in,0,sizeof(in)); int a,b; for(int i=0; i<m; i++) { cin>>a>>b; V[a].push_back(b);//将边保存,也就是将所有信息进行遍历。 in[b]++;//此点入度加1,(b选手在原来输的次数上又输一次) } int k,ans=0; for(int i=1;i<=n;i++) { if(in[i]==0)Q.push(i);//将入度数为零的节点入队。 } while(!Q.empty()) { k=Q.top(); d[ans++]=k; Q.pop();//别忘记pop //开始将所有与此节点连接的边进行删除 while(V[k].size()>0) { int temp=V[k].back(); in[temp]--;//删除后那么这条边指向的节点入度会减1 V[k].pop_back(); if(in[temp]==0)Q.push(temp);//如果这个节点减完之后入度数变为零,那么要入队 } } if(ans<n-1)cout<<-1<<endl;//如果要输出的节点数少于总结点数,那么代表此图有环,不能进行拓扑排序; else { cout<<d[0]; for(int i=1;i<ans;i++) { cout<<" "<<d[i]; } cout<<endl; } } }
    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/zyy_1998/article/details/77159700
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞