• [Noi2010]航空管制


    来自FallDream的博客,未经允许,请勿转载, 谢谢。


    世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生。最近,小X就因为航空管制,连续两次在机场被延误超过了两小时。对此,小X表示很不满意。

    在这次来烟台的路上,小X不幸又一次碰上了航空管制。于是小X开始思考关于航空管制的问题。

    假设目前被延误航班共有n个,编号为1至n。机场只有一条起飞跑道,所有的航班需按某个顺序依次起飞(称这个顺序为起飞序列)。定义一个航班的起飞序号为该航班在起飞序列中的位置,即是第几个起飞的航班。

    起飞序列还存在两类限制条件:

    • 第一类(最晚起飞时间限制):编号为i的航班起飞序号不得超过ki;

    • 第二类(相对起飞顺序限制):存在一些相对起飞顺序限制(a, b),表示航班a的起飞时间必须早于航班b,即航班a的起飞序号必须小于航班b的起飞序号。

    小X思考的第一个问题是,若给定以上两类限制条件,是否可以计算出一个可行的起飞序列。第二个问题则是,在考虑两类限制条件的情况下,如何求出每个航班在所有可行的起飞序列中的最小起飞序号。

    n<=2000 m<=10000 

    第一问 倒着括扑排序,然后每次选择一个限制时间最晚的飞机起飞即可 

    我不会告诉你我一开始倒着改一下时间然后正着括扑排序的

    然后第二个问,对不同的飞机分开计算,忽视目前计算的飞机,直到发现没有飞机可以起飞了,那么那个时间点就是答案啦。

    复杂度n^2logn

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define MN 2000
    #define pa pair<int,int>
    #define mp(x,y) make_pair(x,y)
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,m,head[MN+5],t[MN+5],cnt=0,top=0,q[MN+5],in[MN+5],In[MN+5];
    struct edge{int to,next;}e[20005];
    priority_queue<pa> Q;
    inline void ins(int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;++in[t];}
    
    int Solve(int x)
    {
        memcpy(in,In,sizeof(in));
        in[x]=n;while(!Q.empty()) Q.pop();
        for(int i=1;i<=n;++i) if(!in[i]) Q.push(mp(t[i],i));
        for(int i=n;i;--i)
        {
            if(Q.empty()||Q.top().first<i) return i;
            int x=Q.top().second;Q.pop();
            for(int i=head[x];i;i=e[i].next)
                if(!--in[e[i].to]) Q.push(mp(t[e[i].to],e[i].to));    
        }
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;++i) t[i]=read(); 
        for(int i=1;i<=m;++i) 
        {
            int x=read(),y=read();
            ins(y,x);
        }
        memcpy(In,in,sizeof(In));
        for(int    i=1;i<=n;++i) if(!in[i]) Q.push(mp(t[i],i));
        while(!Q.empty())
        {
            int x=Q.top().second;Q.pop();q[++top]=x;
            for(int i=head[x];i;i=e[i].next)
                if(!--in[e[i].to]) Q.push(mp(t[e[i].to],e[i].to));        
        }    
        for(;top;--top) printf("%d ",q[top]);puts("");
        for(int i=1;i<=n;++i) printf("%d ",Solve(i));
        return 0;
    }
  • 相关阅读:
    C# 上传图片前判断上传图片的宽和高
    PHP调用WebService
    js判断输入字符串长度(汉字算两个字符,字母数字算一个)
    js 验证电话号 座机及手机号
    C# 微信扫码支付 回调页面
    复制文件夹及文件
    html失去获得焦点
    SQL 大数据查询如何进行优化?
    sql表内存占用情况,并进行缩放
    查询被锁的表
  • 原文地址:https://www.cnblogs.com/FallDream/p/Noi2010d2t1.html
Copyright © 2020-2023  润新知