Training 8 - B题
有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
#pragma warning (disable:4996)
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define inf 0X3f3f3f3f
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N = 500 + 5;
const int M = 1000 + 5;
const int maxn = 10000 + 5;
int head[N], ver[M], nex[N];
int deg[N];//入度
int a[N];//top序列
int tot;
int cnt;
int n, m;
void add(int x, int y)
{
++tot;
ver[tot] = y;
nex[tot] = head[x];
head[x] = tot;
deg[y]++;
}
void topsort()
{
priority_queue<int> q;
for (int i = 1; i <= n; i++)
if (deg[i] == 0)
q.push(-i);
while (q.size())
{
int x = -q.top();
q.pop();
a[++cnt] = x;
for (int i = head[x]; i; i = nex[i])
{
int y = ver[i];
if (--deg[y] == 0)
q.push(-y);
}
}
}
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
memset(head, 0, sizeof(head));
memset(ver, 0, sizeof(ver));
memset(nex, 0, sizeof(nex));
memset(deg, 0, sizeof(deg));
tot = cnt = 0;
for (int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
topsort();
for (int i = 1; i <= cnt; i++)
if (i < cnt)
printf("%d ", a[i]);
else
printf("%d\n", a[i]);
}
return 0;
}
思路:
拓朴排序的优先队列板子题。