确定比赛名次
确定比赛名次
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 20 Accepted Submission(s) : 16
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
1 2
2 3
4 3
Sample Output
1 2 4 3
Author
SmallBeer(CML)
Source
杭电ACM集训队训练赛(VII)
题目大意:
输入 N,M,表示有N的点(1~N),和需要输入M条边,下面有M行,每一行输入A,B,表示A的优先级大于B。
问你根据所给的优先级排序,按优先级降序输出的点。
第一次做的时候,只会邻接矩阵,比较简单,不过复杂度会比较高,能够做的数据也不大。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 int InD[505]; 5 int Edge[505][505]; 6 void MakeSet(int Len) 7 { 8 int i; 9 for(i=0;i<=Len;i++) 10 InD[i]=0; 11 return; 12 } 13 int ToPoSort(int n,int* ret) 14 { 15 int i,j,k; 16 for(j=1;j<=n;j++) 17 { 18 for(i=1;i<=n;i++) 19 if(InD[i]==0) 20 { 21 InD[i]--; 22 ret[j]=i; 23 for(k=1;k<=n;k++) 24 if(Edge[i][k]==1) 25 InD[k]--; 26 break; 27 } 28 if(i>n)break; 29 } 30 if(j-1==n) 31 return 1; 32 else 33 return 0; 34 } 35 36 int main() 37 { 38 int N,M,i,a,b,ID[505]; 39 while(scanf("%d%d",&N,&M)!=EOF) 40 { 41 if(N==0&&M==0)return; 42 MakeSet(N); 43 memset(Edge,0,sizeof(Edge)); 44 memset(ID,0,sizeof(ID)); 45 for(i=0;i<M;i++) 46 { 47 scanf("%d%d",&a,&b); 48 if(Edge[a][b]==0) 49 { 50 Edge[a][b]=1; 51 InD[b]++; 52 } 53 } 54 if(ToPoSort(N,ID)) 55 for(i=1;i<=N;i++) 56 { 57 printf("%d",ID[i]); 58 if(i!=N)putchar(32); 59 } 60 putchar(10); 61 62 } 63 return 0; 64 }
修改:2015.5.28 第二次做,改成了邻接表的形式,大大的提高了程序的效率。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <map> 5 #define MAX 505 6 using namespace std; 7 int InD[505];/*InD[i]记录点i的入度*/ 8 int First[MAX];/*First[i]头结点的第一条边的编号*/ 9 struct edge 10 { 11 int TO;/*点*/ 12 int Next;/*下一条边的编号*/ 13 }ID[3*MAX]; 14 int SIGN; 15 void Add_E(int x,int y)/*添加点操作*/ 16 { 17 ID[SIGN].TO=y; 18 InD[y]++; 19 ID[SIGN].Next=First[x]; 20 First[x]=SIGN++; 21 } 22 int Jude(int x,int y)/*查找与X是否与Y相连*/ 23 { 24 int i; 25 for(i=First[x];i!=0;i=ID[i].Next) //查找与该点相关的点 26 { 27 if(ID[i].TO==y)return 0; 28 } 29 return 1; 30 } 31 int ToPoSort(int N,int Num[])/*拓扑排序,邻接表*/ 32 { 33 int i,j,k; 34 for(j=0;j<N;j++) 35 { 36 for(i=1;i<=N;i++) 37 { 38 if(InD[i]==0) 39 { 40 InD[i]--; 41 Num[j]=i; 42 for(k=First[i];k!=0;k=ID[k].Next) 43 { 44 InD[ID[k].TO]--; 45 } 46 break; 47 } 48 } 49 if(i>N)break; 50 } 51 if(j==N)return 1; 52 else return 0; 53 } 54 int main() 55 { 56 int M,N,i; 57 int Num[MAX]; 58 while(scanf("%d%d",&N,&M)!=EOF) 59 { 60 int a,b; 61 if(M==0&&N==0)break; 62 for(i=1;i<=N;i++){First[i]=0;InD[i]=0;} 63 for(i=0,SIGN=1;i<M;i++) 64 { 65 scanf("%d%d",&a,&b); 66 if(Jude(a,b)) /*判断重边*/ 67 { 68 Add_E(a,b); 69 } 70 } 71 if(ToPoSort(N,Num))/*拓扑排序*/ 72 { 73 for(i=0;i<N;i++) 74 { 75 if(i!=0)putchar(32); 76 printf("%d",Num[i]); 77 }putchar(10); 78 } 79 } 80 return 0; 81 }
转载请备注:
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************
**************************************
* 作者: Wurq
* 博客: https://www.cnblogs.com/Wurq/
* Gitee: https://gitee.com/wurq
**************************************