zoukankan      html  css  js  c++  java
  • BZOJ 2535: [Noi2010]Plane 航空管制2

    Description

    世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生。最近,小X就因为航空管制,连续两次在机场被延误超过了两小时。对此,小X表示很不满意。 在这次来烟台的路上,小 X不幸又一次碰上了航空管制。于是小 X开始思考关于航空管制的问题。 假设目前被延误航班共有 n个,编号为 1至n。机场只有一条起飞跑道,所有的航班需按某个顺序依次起飞(称这个顺序为起飞序列)。定义一个航班的起飞序号为该航班在起飞序列中的位置,即是第几个起飞的航班。 起飞序列还存在两类限制条件:  第一类(最晚起飞时间限制):编号为 i的航班起飞序号不得超过 ki;  第二类(相对起飞顺序限制):存在一些相对起飞顺序限制(a, b),表示航班 a的起飞时间必须早于航班 b,即航班 a的起飞序号必须小于航班 b 的起飞序号。 小X 思考的第一个问题是,若给定以上两类限制条件,是否可以计算出一个可行的起飞序列。第二个问题则是,在考虑两类限制条件的情况下,如何求出每个航班在所有可行的起飞序列中的最小起飞序号。

    Input

    第一行包含两个正整数 n和m,n表示航班数目,m表示第二类限制条件(相对起飞顺序限制)的数目。 第二行包含 n个正整数 k1, k2, „, kn。 接下来 m行,每行两个正整数 a和b,表示一对相对起飞顺序限制(a, b),其中1≤a,b≤n, 表示航班 a必须先于航班 b起飞。

    Output

    由两行组成。 
    第一行包含 n个整数,表示一个可行的起飞序列,相邻两个整数用空格分隔。
    输入数据保证至少存在一个可行的起飞序列。如果存在多个可行的方案,输出任
    意一个即可。 
    第二行包含 n个整数 t1, t2, „, tn,其中 ti表示航班i可能的最小起飞序
    号,相邻两个整数用空格分隔。

    Sample Input

    5 5
    4 5 2 5 4
    1 2
    3 2
    5 1
    3 4
    3 1

    Sample Output

    3 5 1 4 2
    3 4 1 2 1

     

    题解:

      这个题目好难想,首先第一问还是比较套路的,我们对于n个点,连一个反图,拓扑排序一下,丢到一个按照点权排序的大根堆了面,正确性还是比较显然的,我们按照拓扑排序的顺序,那么一定满足了条件二的限制,那么用堆来搞,他们的点权就是他们的承受能力,那么承受能力强的排在后面,如果这样还不行,那么此题一定无解,(为什么正着做是错的我也不知道)。

      然后第二问就比较难想了,我们枚举当前要计算答案的点,那么考虑拓扑排序的时候不把他丢到堆里面,直到出现不合法情况的时候,这个时候,就是他最早出现的位置,因为此刻如果还不放他进去,那么必然序列会不合法,所以这个时刻就是这个点的ans.

    代码:

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <queue>
    #define MAXN 200050
    #define RG register
    using namespace std;
    struct node{
        int id,v;
        bool operator < (const node&x)const{
            return x.v>v;
        }
    };
    
    struct edge{
        int first;
        int next;
        int to;
        int quan;
    }a[MAXN*2];
    
    priority_queue<node> q;
    int v[MAXN],in[MAXN],in2[MAXN],ans[MAXN];
    int n,m,num=0;
    
    void addedge(int from,int to){
        a[++num].to=to;
        a[num].next=a[from].first;
        a[from].first=num;
    }
    
    inline void work1(){
        for(RG int i=1;i<=n;i++) in2[i]=in[i];
        for(RG int i=1;i<=n;i++){
            if(!in2[i]) q.push((node){i,v[i]});
        }
        while(!q.empty()){
            int now=q.top().id;q.pop();
            ans[++num]=now;
            for(RG int i=a[now].first;i;i=a[i].next){
                int to=a[i].to;
                in2[to]--;
                if(!in2[to]) q.push((node){to,v[to]});
            }
        }
    }
    
    inline int work2(int k){
        while(!q.empty()) q.pop();
        for(int i=1;i<=n;i++) in2[i]=in[i];
        for(int i=1;i<=n;i++){
            if(i!=k&&!in2[i]) q.push((node){i,v[i]});
        }
        for(RG int hh=n;hh>=1;hh--){
            if(q.empty()||q.top().v<hh) return hh;
            int now=q.top().id;q.pop();
            for(RG int i=a[now].first;i;i=a[i].next){
                int to=a[i].to;
                in2[to]--;
                if(!in2[to]&&to!=k) q.push((node){to,v[to]});
            }
        }
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&v[i]);
        for(int i=1;i<=m;i++){
            int x,y;scanf("%d%d",&x,&y);
            addedge(y,x);in[x]++;
        }
        num=0;
        work1();
        for(int i=num;i>=1;i--) printf("%d ",ans[i]);puts("");
        for(int i=1;i<=n;i++) printf("%d ",work2(i));
        printf("
    ");
        return 0;
    }
  • 相关阅读:
    istio 配置解读
    docker 不同版本 添加--insecure-registry
    Ingress 暴露tcp端口
    jenkins 调用 k8s api
    十五项指标衡量DevOps是否成功
    关于使用镜像仓库的思考
    Jenkins pipeline:pipeline 语法详解
    lvm xfs 扩容
    看到了一个pipeline例子,
    私有仓库harbor安装包括https
  • 原文地址:https://www.cnblogs.com/renjianshige/p/7667946.html
Copyright © 2011-2022 走看看