• [CF1463E] Plan of Lectures


    [CF1463E] Plan of Lectures - 拓扑排序,并查集

    Description

    构造一个 1..n 的排列,有一些限制:指定了一些 (ai,i) 要求 ai 出现在 i 的前面,指定了一些 (i,j) 要求 i 一定在 j 之前一个位置

    Solution

    先考虑第二类条件,用类似并查集的方法来串串,最后我们把一个点往后几个固定的点都找出来,同时判断是否有环路

    接下来缩点(选取链头作为代表点)然后跑拓扑排序

    跑完拓扑以后,我们把得到的序列展开(缩点还原),然后检查一遍所有条件是否满足即可

    (第一遍写的时候把两种条件看反了)

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    int n, m;
    int fa[N];
    pair<int, int> e[N];
    vector<int> toposeq;
    vector<int> g[N];
    int vis[N], ind[N];
    list<int> ls[N];
    vector<int> seq;
    int a[N];
    
    int find(int p)
    {
        return p == fa[p] ? p : fa[p] = find(fa[p]);
    }
    
    void dfs(int p)
    {
        vis[p] = 1;
        for (auto q : g[p])
            if (vis[q] == 0)
            {
                dfs(q);
            }
        toposeq.push_back(p);
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            fa[i] = i, ls[i].push_back(i);
        for (int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            cin >> u >> v;
            int p = find(u), q = find(v);
            if (p == q)
            {
                cout << 0 << endl;
                return 0;
            }
            else
            {
                fa[q] = p;
                ls[p].splice(ls[p].end(), ls[q]);
            }
        }
        for (int i = 1; i <= n; i++)
        {
            if (a[i] == 0)
                continue;
            int u = a[i], v = i;
            e[i] = {u, v};
            if (find(u) == find(v))
                continue;
            g[find(u)].push_back(find(v));
            ind[find(v)]++;
        }
        for (int i = 1; i <= n; i++)
            if (ind[i] == 0 && find(i) == i)
                dfs(i);
        reverse(toposeq.begin(), toposeq.end());
        for (auto p : toposeq)
        {
            for (auto i : ls[p])
            {
                seq.push_back(i);
            }
        }
        vector<int> inv(n + 2);
        for (int i = 0; i < seq.size(); i++)
            inv[seq[i]] = i;
        for (int i = 1; i <= n; i++)
        {
            if (a[i] == 0)
                continue;
            int u = a[i], v = i;
            if (inv[v] < inv[u])
            {
                cout << 0 << endl;
                return 0;
            }
        }
        if (seq.size() == 0)
        {
            cout << 0 << endl;
            return 0;
        }
        for (int i = 0; i < seq.size(); i++)
            cout << seq[i] << " ";
        cout << endl;
    }
    
  • 相关阅读:
    价格与用户权限
    bootstrap-validator
    关于项目管理的感想
    rabbitmq使用日记
    matplotlib
    JS滑动到页面底部
    排序算法思想
    杀死指定进程
    pycharm的一些快捷键
    对支付宝支付的理解
  • 原文地址:https://www.cnblogs.com/mollnn/p/14474656.html
Copyright © 2020-2023  润新知