• E. Plan of Lectures(给定拓扑图求输出序列满足存在给定链)


    题:https://codeforces.com/contest/1463/problem/E

    题意:给定拓扑图,在给定链(以边的形式给出),问是否能在拓扑顺序中找出一个序列使得这个序列包含给定的链(x->y->z)。

    分析:

    • 给定的拓扑图我们可以当作一个DAG,然后给定的m个边我们可以在原图上进行缩点,缩成的点一定得是一条链;
    • 判断这些链会不会构成环;
    • 构建新图G,再判断是否能构成拓扑序列,再把压缩的点解压出来
    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    const int M=3e5+5;
    int p[M],vis[M],nex[M],in[M],rt[M],rnk[M],cmp[M];
    vector<int>G[M],ans;
    queue<int>que;
    int main(){
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&p[i]);
        for(int u,v,i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            nex[u]=v;
            vis[v]=1;///在不是链头就标记
        }
        int tot=0;
        for(int i=1;i<=n;i++){
            if(vis[i]) continue;
            cmp[i]=++tot;
            int now=0,x=nex[i];
            rnk[i]=now;
            rt[tot]=i;
            while(x!=0&&cmp[x]==0){
                rnk[x]=++now;
                cmp[x]=tot;
                x=nex[x];
            }
        }
        for(int i=1;i<=n;i++)///check circle
            if(!cmp[i]||(cmp[p[i]]==cmp[i]&&rnk[i]<rnk[p[i]])) return puts("0"),0;
    
        for(int i=1;i<=n;i++){///construct new graph
            if(p[i]==0) continue;
            if(cmp[i]!=cmp[p[i]]){
                G[cmp[p[i]]].pb(cmp[i]);
                in[cmp[i]]++;
            }
        }
    
        ///tuopu
        for(int i=1;i<=tot;i++)
            if(in[i]==0)
                que.push(i);
        while(!que.empty()){
            int u=que.front();que.pop();
            ans.pb(u);
            for(auto v:G[u])
                if(--in[v]==0) que.push(v);
        }
        if(ans.size()==tot){
            for(auto v:ans){
                int nowi=rt[v];
                while(nowi!=0){
                    printf("%d ",nowi);
                    nowi=nex[nowi];
                }
            }
        }
        else puts("0");
        return 0;
    }
    View Code
  • 相关阅读:
    NAT(网络地址转换)
    go从文件中读取json字符串并转换
    实现守护进程
    c++ uconcontext.h实现协程
    bzoj 1085骑士精神
    在线代码评测机
    基于时间轮的定时器
    内存管理(一)
    二叉树的先序中序后序(非递归)
    RDD操作
  • 原文地址:https://www.cnblogs.com/starve/p/14159059.html
Copyright © 2020-2023  润新知