拓扑排序+优先队列——确定比赛名次

确定比赛名词

P r o b l e m D e s c r i p t i o n \color{blue}Problem Description ProblemDescription
N N N个比赛队 ( 1 < = N < = 500 ) (1<=N<=500) 1<=N<=500,编号依次为 1 , 2 , 3... N 1,2,3...N 1,2,3...N,进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前。现在请你编程序确定排名。

I n p u t \color{blue}Input Input
输入有若干组,每组中的第一行为二个数 N ( 1 < = N < = 500 ) , M N(1<=N<=500),M N1<=N<=500M;其中N表示队伍的个数, M M M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数P1,P2表示即P1队赢了P2队。

O u t p u t \color{blue}Output Output
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。

其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。

S a m p l e I n p u t \color{blue}Sample Input SampleInput

4 3
1 2
2 3
4 3

S a m p l e O u t p u t \color{blue}Sample Output SampleOutput

1 2 4 3

如果 a a a战胜 b b b,我们可以假设有一条边从 a a a连向 b b b,然后我们设置一个数组 r [ ] r[] r[],表示战败的次数,那么r[b]++。之后就进行拓扑排序输出就行了,要注意输出时编号小的在前面,那么就可以借助优先队列来完成。

#include 
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
#define endl '\n'
#define pb(a) push_back(a)
#define ALL(x) x.begin(), x.end()
#define SIZE(x) int(x.size())
#define IOS ios::sync_with_stdio(0);
int r[510];
vector<int> g[510];
bool vis[510];
int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        memset(r, 0, sizeof(r));
        memset(vis, 0, sizeof(vis));
        for (int i = 1; i <= n; ++i) g[i].clear();
        
        for (int i = 0; i < m; ++i) {
            int u, v;
            scanf("%d%d", &u, &v);
            r[v]++;
            g[u].pb(v);
        }
        
        //拓扑排序模板
        priority_queue<int, vector<int>, greater<int>> q;
        for (int i = 1; i <= n; ++i)
            if (!r[i]) q.push(i); //先把可以第一名的入列
        vector<int> ans;
        while (!q.empty()) {
            int u = q.top(); //编号最小的出列
            q.pop();
            ans.pb(u);
            vis[u] = 1;
            for (int i = 0; i < SIZE(g[u]); ++i) {
                int v = g[u][i];
                if (!vis[v] && --r[v] == 0) {
                    q.push(v);
                }
            }
        }
        
        for (int i = 0; i < n - 1; ++i) printf("%d ", ans[i]);
        printf("%d\n", ans[n - 1]);
    }
    return 0;
}

你可能感兴趣的:(拓扑排序+优先队列——确定比赛名次)