1. 程式人生 > >HDU 1285 確定比賽名次(拓撲排序大頂堆)

HDU 1285 確定比賽名次(拓撲排序大頂堆)

條件 its nbsp 行為 acm auth gre tom while

Problem Description 有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

Author SmallBeer(CML)

Source 杭電ACM集訓隊訓練賽(VII)
#include<bits/stdc++.h>
using namespace std;

int n,m,d[510],x,y;
bool
f[510][510],flag;// f是建邊,也就是存圖 priority_queue<int,vector<int>,greater<int> >q;//建立一個小頂堆,升序排列 void BFS() { while(!q.empty()) { int t = q.top(); q.pop(); if(flag) printf(" %d",t); else { printf("%d",t); flag
= 1; } for(int i = 1;i <= n; ++i) if(f[t][i])//如果這條邊存在,且沒遍歷過 { f[t][i] = 0;//標記為遍歷過 d[i]--;//入度減 if(d[i] == 0) q.push(i); } } } int main() { while(~scanf("%d%d",&n,&m)) { memset(f,0,sizeof(f));//清空圖 memset(d,0,sizeof(d));//清空入度 for(int i = 1;i <= m; ++i) { scanf("%d%d",&x,&y); if(!f[x][y])//確保沒有重復的邊 { f[x][y] = 1;//建邊 d[y]++;//入度 } } while(!q.empty())q.pop(); for(int i = 1;i <= n; ++i)//尋找根節點(入度為0) if(!d[i]) q.push(i); flag = 0; BFS();//拓撲狂搜 printf("\n"); } return 0; }

HDU 1285 確定比賽名次(拓撲排序大頂堆)