題目原文
眾所周知, TT 是一位重度愛貓人士,他有一只神奇的魔法貓。
有一天,TT 在 B 站上觀看貓貓的比賽。一共有 N 只貓貓,編號依次為1,2,3,…,N進行比賽。比賽結(jié)束后,Up 主會為所有的貓貓從前到后依次排名并發(fā)放愛吃的小魚干。不幸的是,此時 TT 的電子設(shè)備遭到了宇宙射線的降智打擊,一下子都連不上網(wǎng)了,自然也看不到最后的頒獎典禮。
不幸中的萬幸,TT 的魔法貓將每場比賽的結(jié)果都記錄了下來,現(xiàn)在他想編程序確定字典序最小的名次序列,請你幫幫他。
Input
輸入有若干組,每組中的第一行為二個數(shù)N(1<=N<=500),M;其中N表示貓貓的個數(shù),M表示接著有M行的輸入數(shù)據(jù)。接下來的M行數(shù)據(jù)中,每行也有兩個整數(shù)P1,P2表示即編號為 P1 的貓貓贏了編號為 P2 的貓貓。
Output
給出一個符合要求的排名。輸出時貓貓的編號之間有空格,最后一名后面沒有空格!
其他說明
符合條件的排名可能不是唯一的,此時要求輸出時編號小的隊伍在前;輸入數(shù)據(jù)保證是正確的,即輸入數(shù)據(jù)確保一定能有一個符合要求的排名。
Sample Input
4 3
1 2
2 3
4 3
Sample Output
1 2 4 3
解題思路
由于排名有先后性,且要求輸出排名,故考慮用拓?fù)渑判驅(qū)崿F(xiàn)。
由于符合條件的輸出有多種,題目要求輸出字典序最小的答案,因此將拓?fù)渑判蛑械年犃懈臑閮?yōu)先隊列(最大優(yōu)先隊列,由于要從小到大排序,因此存入時存入原值的相反數(shù),輸出時,輸出值乘以-1還原),并在每次數(shù)據(jù)出隊列時,用score[]數(shù)組記錄每只貓貓的編號。
最后按輸出格式要求輸出score[].
實現(xiàn)代碼
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=510;
int n,m;
bool cat[maxn][maxn];
int d[maxn];
int score[maxn];
int cnt;
void toposort(){
cnt=0;
priority_queue<int>q;
for(int i=1;i<=n;i++)
{
if(d[i]==0)
q.push(-i);
}
while(!q.empty())
{
int x=-q.top();
q.pop();
score[++cnt]=x;
//判斷刪除節(jié)點能到達的點的
for(int y=1;y<=n;y++)
{
if(cat[x][y])
{
d[y]--;
if(d[y]==0)
{
q.push(-y);
}
}
}
}
}
int main(){
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(cat,0,sizeof(cat));
memset(d,0,sizeof(d));
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
if(cat[x][y]==1)
continue;
cat[x][y]=1;
d[y]++;
}
toposort();
bool mark=0;
for(int i=1;i<=n;i++)
{
if(!mark)
{
printf("%d",score[i]);
mark=1;
}
else
printf(" %d",score[i]);
}
printf("\n");
}
return 0;
}
小結(jié)
在隊列值需要排序時,優(yōu)先考慮用堆(優(yōu)先隊列)解決,比手寫比較方法簡單快捷。