題目鏈接
因爲輸出格式不對錯了幾次,用到了拓撲排序的思路,不過寫本題目的時候最耗時間的是研究自定義優先隊列排序的方法。
#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;
}
}