Bzoj2535 [Noi2010]Plane 航空管制2

2535: [Noi2010]Plane 航空管制2

Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 722  Solved: 456

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

HINT

Source

鸣谢Benz

反向存边,并将每架飞机的起飞限制x改成n-x,就将问题转化成一个求飞机最晚起飞时间的问题,用拓扑排序可解。

如何求每架飞机的最小起飞次序? 在新问题中,每次限制不起飞某架飞机p,而将其他能飞的飞机都飞出去(拓扑排序时不处理p结点,让p连出去的边都保留下来),此时飞机p必须起飞了,这个时间就是它在新问题中的最晚起飞时间,也就是原问题中的最早起飞时间。

  1 /**************************************************************
  2     Problem: 2535
  3     User: SilverN
  4     Language: C++
  5     Result: Accepted
  6     Time:1296 ms
  7     Memory:3284 kb
  8 ****************************************************************/
  9
 10 #include<algorithm>
 11 #include<iostream>
 12 #include<cstring>
 13 #include<cstdio>
 14 #include<cmath>
 15 #include<queue>
 16 using namespace std;
 17 const int mxn=30000;
 18 int read(){
 19     int x=0,f=1;char ch=getchar();
 20     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 21     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 22     return x*f;
 23 }
 24 //bas
 25 int n,m;
 26 //plane
 27 struct plane{
 28     int id;
 29     int limit;
 30 }p[mxn];
 31 int cmp(plane a,plane b){return a.limit<b.limit;}
 32 //edge
 33 struct edge{//存边,若a必须早于b起飞,则存一条从b到a的边
 34     int v;
 35     int nxt;
 36 }e[mxn];
 37 int hd[mxn],mct=0;
 38 void add_edge(int u,int v){
 39     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;
 40     return;
 41 }
 42
 43 //拓扑排序
 44 int limit[mxn];
 45 int ind[mxn];
 46 int top=0;
 47 int ans[mxn];
 48 int deg[mxn];
 49 /*
 50 queue<int>q;
 51 void solve(int x){
 52     memcpy(deg,ind,sizeof ind);
 53     while(!q.empty()) q.pop();
 54     int i,j;
 55     top=0;
 56     int pos=1;
 57     for(i=1;i<=n;i++){
 58         for(;pos<=n && p[pos].limit<i;pos++){
 59             int v=p[pos].id;
 60             if(!deg[v] && x!=v){
 61                 q.push(v);
 62                 ans[++top]=v;
 63             }
 64         }
 65         if(q.empty())break;
 66         int u=q.front();q.pop();
 67         for(j=hd[u];j;j=e[j].nxt){
 68             int v=e[j].v;
 69             deg[v]--;
 70             if(!deg[v] && v!=x && limit[v]<i){
 71                 q.push(v);
 72                 ans[++top]=v;
 73             }
 74         }
 75     }
 76     return;
 77 }*/
 78 int head,tail;
 79 int q[mxn<<3];
 80 void solve(int x){//不安排x
 81     int pos,i,j,u,v;
 82     memcpy(deg,ind,sizeof ind);
 83     head=tail=0;
 84     for(i=1,pos=1;i<=n;i++){
 85         for(;pos<=n && p[pos].limit<i;pos++){
 86             int v=p[pos].id;
 87             if(!deg[v] && x!=v){
 88 //              printf("test2:%d %d\n",deg[v],v);
 89                 q[++tail]=v;
 90             }
 91         }
 92         if(head<tail){
 93             u=q[++head];
 94             for(j=hd[u];j;j=e[j].nxt){
 95                 int v=e[j].v;
 96                 deg[v]--;
 97                 if(!deg[v] && v!=x && limit[v]<i){
 98 //                  printf("test3:%d %d\n",deg[v],v);
 99                     q[++tail]=v;
100                 }
101             }
102         }
103         else return;
104     }
105     return;
106 }
107
108 //main
109 int main(){
110     int i,j;
111     n=read();m=read();
112     for(i=1;i<=n;i++){
113         p[i].limit=read();
114         p[i].limit=n-p[i].limit;
115         p[i].id=i;
116         limit[i]=p[i].limit;
117     }
118     int u,v;
119     sort(p+1,p+n+1,cmp);
120     for(i=1;i<=m;i++){
121         u=read();v=read();
122         ind[u]++;
123         add_edge(v,u);
124     }
125     solve(0);
126     for(i=tail;i;i--)printf("%d ",q[i]);
127 //  for(i=top;i;i--)printf("%d ",ans[i]);
128     printf("\n");
129     for(i=1;i<=n;i++){
130         solve(i);
131         printf("%d ",n-tail);
132     }
133     return 0;
134 }
时间: 2024-11-02 10:57:23

Bzoj2535 [Noi2010]Plane 航空管制2的相关文章

2109&amp;2535: [Noi2010]Plane 航空管制 - BZOJ

Description世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上,小 X不幸又一次碰上了航空管制.于是小 X开始思考关于航空管制的问题. 假设目前被延误航班共有 n个,编号为 1至n.机场只有一条起飞跑道,所有的航班需按某个顺序依次起飞(称这个顺序为起飞序列).定义一个航班的起飞序号为该航班在起飞序列中的位置,即是第几个起飞的航班. 起飞序列还存在两类限制条件:

[Noi2010]Plane 航空管制 贪心

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 2100 #define M 11000 int t[N]; int n,m; int dp[N]; int ru[N],op[N]; int e[N],ne[M],v[M]; int nn,been1[N],been2[N]; int q[N],he

bzoj 2109: [Noi2010]Plane 航空管制

Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频 发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此, 小X表示很不满意. 在这次来烟台的路上,小 X不幸又一次碰上了航空管制.于是小 X开始思考 关于航空管制的问题. 假设目前被延误航班共有 n个,编号为 1至n.机场只有一条起飞跑道,所 有的航班需按某个顺序依次起飞(称这个顺序为起飞序列).定义一个航班的起 飞序号为该航班在起飞序列中的位置,即是第几个起飞的航班. 起飞序列还存在两类

BZOJ2109 [Noi2010]Plane 航空管制

Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频 发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此, 小X表示很不满意. 在这次来烟台的路上,小 X不幸又一次碰上了航空管制.于是小 X开始思考 关于航空管制的问题. 假设目前被延误航班共有 n个,编号为 1至n.机场只有一条起飞跑道,所 有的航班需按某个顺序依次起飞(称这个顺序为起飞序列).定义一个航班的起 飞序号为该航班在起飞序列中的位置,即是第几个起飞的航班. 起飞序列还存在两类

BZOJ2109 NOI2010 Plane 航空管制 拓扑排序

题意:给定两种限制:1.编号为i的航班必须在ki+1之前起飞  2.(a,b)表示a必须在b之前起飞.求:1.一个合法起飞序列  2.每个航班在所有合法起飞顺序中,最早的起飞时间.问题保证有解 题解:首先按照第二个限制条件建图,那么第一问随便跑一个拓扑序就好,关键在第二问,我们枚举每一个飞机,假定该飞机不存在,不断往拓扑序中加点,直到没法再加点(不存在一个空的位置t满足存在一个节点i满足t∈[N-ki+1,N])为止,这样求出来的位置就是答案. #include <cstdio> #inclu

bzoj 2535 &amp;&amp; bzoj 2109 [Noi2010]Plane 航空管制——贪心

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2535 https://www.lydsy.com/JudgeOnline/problem.php?id=2109 考虑按拓扑序决策,发现不太行:主要是一种情况:虽然自己的 k[ ] 靠后,但自己限制的点的 k[ ] 靠前. 这样的话,自己应该尽量往前放:但为了别的点的这种情况,自己又应该尽量往后放,所以无法决策了. 发现这种情况主要和后面的点是否紧急有关.所以就是虽然拓扑序是那样的,但可以

BZOJ 2535 Plane 航空管制2

http://www.lydsy.com/JudgeOnline/problem.php?id=2535 思路:对于1,我们只需要每个点比前驱大就可以了,然后满足尽量优. 对于第二问,我们先求出这个点前驱有几个,记为ans,cnt=ans 每访问一个未访问的点,cnt++ 然后对于后面的点从少往大排,若有k>ans,那么一定在我们当前处理这个点前面,ans++ 若有k<=cnt,说明要i放在这个点的后面,因此ans=k+1 记得不要省方便add(read(),read()),好像会出错. 1

NOI2010航空管制

2008: [Noi2010]航空管制 Time Limit: 10 Sec  Memory Limit: 552 MBSubmit: 31  Solved: 0[Submit][Status] Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上,小X不幸又一次碰上了航空管制.于是小X开始思考关于航空管制的问题. 假设目前被延误航班共有n个,编号为

[NOI2010] 航空管制

题目描述 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此,小X表示很不满意. 在这次来烟台的路上,小X不幸又一次碰上了航空管制.于是小X开始思考关于航空管制的问题. 假设目前被延误航班共有n个,编号为1至n.机场只有一条起飞跑道,所有的航班需按某个顺序依次起飞(称这个顺序为起飞序列).定义一个航班的起飞序号为该航班在起飞序列中的位置,即是第几个起飞的航班. 起飞序列还存在两类限制条件: • 第一类(最晚起飞