標籤:des style http java color os strong 資料
| 【BestCoder Round #3 來了!】8月3號19:00~21:00(賽前30分鐘停止註冊比賽) |
確定比賽名次Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 11642 Accepted Submission(s): 4634
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 Input4 31 22 34 3
Sample Output1 2 4 3
AuthorSmallBeer(CML)
Source 杭電ACM集訓隊訓練賽(VII) |
題目分析:此題是拓撲排序的基本題!
先介紹何為拓撲排序,將一堆資料元素按照某種 關係順序 排列起來。
把每個變數看成一個點,把“關係”看成有向邊,我們會得到一個有向圖。我們的任務是知道電腦把一個圖的所有結點排序。
在圖論中,這個問題稱為拓撲排序。
演算法分析:拓撲排序基於鄰接表的思想很好理解,具體實現則比較難。
也可以採用鄰接矩陣的方式處理,演算法如下:
建立map鄰接矩陣,賦初始值(非1)。建立一個特殊的處理數組不如 in[N]; 此數組用來記憶次數,初始賦0,如果是1->2的關係,則
in[2]++; 還有3也->2,那就再加,就是in[指向目標]++;
開闢儲存棧,用來儲存一次進棧的資料!建立toposort函數處理in[]和map[][]。 迴圈遍曆n(元素數)次,每次會有元素進入儲存棧。
在每次大迴圈中對於in[]數組開始遍曆in[]的元素是否為0,若為0則說明為 無入度的結點,邊把它進棧。並且把與它有最近關係的in[]-1.
然後。。。。。。
代碼如下:(仔細閱讀便會理解此演算法)
#include <stdio.h>
#include <string.h>
int map[502][502];
int in[502];
int s[502], k;
int n, m;
void tpsort()
{
int m;
m = n;
int i, j;
while(m--)
{
for(i=1; i<=n; i++)
{
if(in[i]==0)
{
s[k++] = i;
in[i]-=1;
for(j=1; j<=n; j++)
{
if(map[i][j]==1)
{
in[j]-=1;
}
}
break;
}
}
}
for(i=0; i<k; i++)
{
printf("%d%c", s[i],i==k-1?‘\n‘:‘ ‘);
}
}
int main()
{
int i, j;
int a, b;
while(scanf("%d %d", &n, &m)!=EOF)
{
k=0;
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
map[i][j] = -1;
}
}
memset(in, 0, sizeof(in));
for(j=0; j<m; j++)
{
scanf("%d %d", &a, &b );
if(map[a][b] == -1 )
{
map[a][b] = 1;
in[b]++;
}
}
tpsort();
}
return 0;
}