• 「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;
    }
    
  • 相关阅读:
    dd if=/dev/zero of=/dev/null 使用
    Linux 下的dd命令使用详解以及dd if=/dev/zero of=的含义
    windows 以及 linux 查看时间
    Linux下vi命令大全(文件修改)
    python test online
    python ssh登录下载上传脚本
    python telnet 中的数据判断(或者执行cmd后返回的数据 OperatingSystem.Run)
    python 转化串口中的数据 ,并分组判断
    python cmd下关闭exe程序(关闭浏览器驱动)
    robot 网卡连接情况
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12256206.html
Copyright © 2020-2023  润新知