題目描述
JH和他的好朋友YZ兩名程序員回訪母校合工大,準備在這住一段日子,都說“玩在安大,喫在工大”,JH又是一名典型喫貨,於是決定在工大食堂好好喫一段日子,但是,面對美食誘惑:黃燜雞、風暴乾鍋、麻辣香鍋、奧爾良烤翅…由於時間有限,JH不知道哪頓飯喫哪個菜好。 於是YZ爲了幫助他解決這個問題,也順便考考他,給他出了一個問題:“黃燜雞必須在乾鍋花菜前面喫,乾鍋牛肉必須在乾鍋魷魚前面喫….你按這個要求下,就知道喫的順序啦”。JH抓抓頭,分分鐘寫了個程序搞定,現在,讓你來寫寫看?輸出一組JH符合條件下喫的食物的序列。 假設JH每頓只吃一種食物,且每頓喫的都不同,食物編號1到N。
輸入
先輸入一個整數T,表示T(T < 50)組數據。 每組數據第一行輸出一個整數,N,M,分別表示有N種食物,總共有M個約束條件,接下來M行每行輸入兩個正整數a,b( n > = a > 0,n > = b > 0),表示食物a必須在食物b之前喫。
輸出
各組數據輸出答案佔一行,輸出一組符合條件的序列(要求輸出字典序最大的那一組),如果答案不存在,輸出“-1”。
樣例輸入
1
4 3
1 2
2 3
4 3
樣例輸出
4 1 2 3
思路
此題主要運用拓撲排序
- 首先讀取數據,存入一個圖中,同時記錄每個節點的入度;
- 然後再將入度爲0的節點加入都優先隊列中;
- 取優先隊列的隊首元素,並將此元素存到數組result中,然後依次遍歷此節點的鄰接點,同時將鄰接點的入度減1,並將鄰接點中入度爲0的加入到優先隊列中;
- 重複步驟三,直到隊列爲空;
code
#include <iostream>
#include <queue>
#include <cstring>
#include <fstream>
using namespace std;
int G[1005][1005];
bool vis[1005];
int n, m;
bool isStart(int k)
{
for(int i = 0; i <= n; i ++)
{
if(G[i][k])
{
return false;
}
}
return true;
}
bool hasHoop()
{
for(int i = 1; i <= n; i ++)
{
if(!vis[i])
{
return true;
}
}
return false;
}
void Do()
{
priority_queue<int> pq;
int loc = 0;
int ans[1005];
for(int i = 1; i <= n; i++)
{
if(isStart(i))
{
pq.push(i);
}
}
while(!pq.empty())
{
//cout << "11" << endl;
int k = pq.top();
pq.pop();
if(vis[k])
{
continue;
}
ans[loc++] = k;
vis[k] = true;
for(int i = 1; i <= n; ++ i)
{
G[k][i] = 0;
if(isStart(i))
{
pq.push(i);
}
}
}
if(hasHoop())
{
cout << "-1" << endl;
}
else
{
for(int i = 0; i < n; i ++)
{
if(i)
{
cout << " ";
}
cout << ans[i];
}
cout << endl;
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
//ifstream cin("data.in");
int T;
cin >> T;
while(T --)
{
cin >> n >> m;
memset(G, 0, sizeof(G));
memset(vis, false, sizeof(vis));
for(int i = 0; i < m; i ++)
{
int a, b;
cin >> a >> b;
G[a][b] = 1;
}
Do();
}
return 0;
}