题目链接
因为输出格式不对错了几次,用到了拓扑排序的思路,不过写本题目的时候最耗时间的是研究自定义优先队列排序的方法。
#include<iostream>
#include<queue>
#include<functional>
using namespace std;
typedef struct Node
{
queue<int> list;//记录后继结点
int degree;//记录入度
int num;//记录自己的序号
int is;//记录该节点是否已经取出
}Node;
bool operator > ( Node a,Node b) //这里的参数如果是Node* 并不知道为什么
{
return a.num > b.num; //自定义排序从小到大
};
int main()
{
priority_queue<Node,vector<Node>,greater<Node>> queue; //优先队列
int n,m;
int i,j;
Node a[500];
int sum = 0;
while(scanf("%d %d",&n,&m)!=EOF)
{
for(int i =0;i<n;i++)
{
Node temp = Node(); //创建节点
temp.degree = 0;//初始化入度为0
temp.num = i;//赋值节点序号 代表队伍代号
temp.is = 0; //初始化节点未取出
a[i] = temp; //进入数组
}
for(int s=0;s<m;s++)
{
scanf("%d %d",&i,&j); //输入队伍比赛结果
a[j-1].degree++; //失败队伍入度加1
a[i-1].list.push(j-1); //失败队伍作为胜利队伍的后继节点添加到胜利队伍结构体的list里
}
for(int s=0;s<n;s++)//第一次遍历 找到入度为0的节点压入有限队列 ,为什么从小到大排序,因为题目要求,小序号的队伍排在前面
{
if(a[s].degree == 0)
{
a[s].is = 1; //当前节点取出
queue.push(a[s]);//入优先队列
}
}
while(!queue.empty())//当优先队列不为空
{
while(queue.top().list.size()) //遍历当前节点的后继节点
{
a[queue.top().list.front()].degree--;//后继节点入度减1
queue.top().list.pop();//当前后继节点出队列
}
if(sum < n-1) //控制输出格式
{
printf("%d ",queue.top().num+1);
sum++;
}
else
{
printf("%d\n",queue.top().num+1);
}
queue.pop();
for(int i =0;i<n;i++) //一次出队后再次遍历数组 ,查找当前入度为0 的节点,继续入队列
{
if(a[i].degree == 0 && a[i].is == 0) //如果当前节点入度为0 且此时并未被取出 ,不加这个条件会把已经出优先队列的节点再进队列
{
a[i].is = 1; //当前节点取出
queue.push(a[i]);//进队列
}
}
}
sum = 0;
}
}