• 「JSOI2010」排名


    「JSOI2010」排名

    传送门
    看到先后顺序限制和字典序,很容易想到拓扑排序 + 贪心。
    考虑具体做法:
    对于第一问:
    我们开一个大根堆来代替队列,然后从大到小构造出各个元素的排名。
    我们连边 (i o a_i) ,表示 (i) 要在 (a_i) 后面,也就是满足 (a_i)(i) 前面。
    然后我们拓扑排序的时候每次取出的都是当前编号最大的并把它放在后面,也就满足了字典序尽量小的原则。
    对于第二问:
    我们还是考虑用堆来代替队列,但此时是要使得字典序尽量大,所以我们改为连边 (a_i o i) ,然后从小到大构造排名即可。
    (p.s. 但是这题数据好奇怪啊,我一开始在第二问的拓扑排序里面,写成每个节点直接往堆里丢,居然也过了???)
    参考代码:

    #include <cstring>
    #include <cstdio>
    #include <queue>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
     
    const int _ = 2e5 + 5;
     
    int tot, head[_]; struct Edge { int ver, nxt; } edge[_];
    inline void Add_edge(int u, int v) { edge[++tot] = (Edge) { v, head[u] }, head[u] = tot; }
     
    int n, a[_], dgr[_], rank, ans[_];
    priority_queue < int > Q;
     
    inline void solve1() {
        for (rg int i = 1; i <= n; ++i) if (a[i] != 0) Add_edge(i, a[i]), ++dgr[a[i]];
        for (rg int i = 1; i <= n; ++i) if (dgr[i] == 0) Q.push(i);
        rank = n;
        while (!Q.empty()) {
            int u = Q.top(); Q.pop(), ans[u] = rank--;
            for (rg int i = head[u]; i; i = edge[i].nxt) if (!--dgr[edge[i].ver]) Q.push(edge[i].ver);
        }
        for (rg int i = 1; i <= n; ++i) printf("%d%c", ans[i], " 
    "[i == n]);
    }
     
    inline void solve2() {
        tot = 0, memset(head, 0, sizeof head);
        for (rg int i = 1; i <= n; ++i) if (a[i] != 0) Add_edge(a[i], i), ++dgr[i];
        for (rg int i = 1; i <= n; ++i) if (dgr[i] == 0) Q.push(i);
        rank = 1;
        while (!Q.empty()) {
            int u = Q.top(); Q.pop(), ans[u] = rank++;
            for (rg int i = head[u]; i; i = edge[i].nxt) if (!--dgr[edge[i].ver]) Q.push(edge[i].ver);
        }
        for (rg int i = 1; i <= n; ++i) printf("%d%c", ans[i], " 
    "[i == n]);
    }
     
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        read(n);
        for (rg int i = 1; i <= n; ++i) read(a[i]);
        solve1();
        solve2();
        return 0;
    }
    
  • 相关阅读:
    按不同通道加载不同弹幕数据的实现方法
    webpack手动配置Vue项目
    flex布局是什么?
    npm packson.json介绍
    npm使用介绍
    Vue路由机制
    VUE双向绑定原理
    常用API接口汇总
    C# MVC权限验证
    C# 正则表达式大全
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12256206.html
Copyright © 2020-2023  润新知