拓扑排序
例题: 确定比赛名次
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
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 #define ll long long 5 #define pi acos(-1) 6 #define mod 1000000007 7 #define maxn 10005 8 9 int n, m, counter = 0; 10 int a[505][505];//记录两个结点是否相连 11 int ans[505], indeg[505];//ans答案数组 indeg入度数组 12 priority_queue<int, vector<int>, greater<int>> q;//优先队列 小顶 13 14 void topo_sort(); 15 16 int main() { 17 while(~scanf("%d%d", &n, &m)) { 18 int win, los; 19 counter = 0; 20 memset(indeg, 0, sizeof(indeg)); 21 memset(ans, 0, sizeof(ans)); 22 for(int i = 1; i <= m; i++) {//建图 23 scanf("%d%d", &win, &los); 24 if(!a[win][los]) { 25 a[win][los] = 1;//win是los的前驱 26 indeg[los]++;//所以los入度加一 27 } 28 29 } 30 topo_sort();//拓扑排序 31 for(int i = 0; i < n; i++) { 32 printf("%d", ans[i]); 33 if(i != n - 1) 34 printf(" "); 35 } 36 printf("\n"); 37 } 38 return 0; 39 } 40 41 42 43 void topo_sort() { 44 for(int i = 1; i <= n; i++) { 45 if(!indeg[i]) q.push(i);//入度为0则入队列 46 } 47 while(!q.empty()) {//访问所有入度为零的结点的相关结点 48 int t = q.top();//先从顶(最小的)开始 49 ans[counter++] = t;//记录 50 q.pop();//出队 51 for(int i = 1; i <= n; i++) {//遍历所有结点 52 if(a[t][i]) {//不为零 说明i是t指向的结点 53 indeg[i]--;//所以i入度-1 54 if(!indeg[i]) q.push(i);//如果入度变为了0 入队 55 a[t][i] = 0;//单组输入可以不管 56 } 57 } 58 } 59 } 60 //for(int i = 0; i < n; i++)
学习资料 https://www.bilibili.com/video/BV1PW41187Mz
https://www.luogu.com.cn/blog/80049/kuai-su-ru-shou-ta-pu-pai-xu