首页 > 代码库 > 2109&2535: [Noi2010]Plane 航空管制 - BZOJ

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

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

 

orz VFK

首先把边反过来,k[i]变成n-k[i],整个序列反过来

就变成另一个问题了,就是点i的序号必须大于k[i],还有许多关系(a,b)表示a必须在b前面出现

然后要求一个可行序列和每个点最晚出现的时间

求可行序列就直接拓扑排序

求最晚出现时间就枚举点i

我们先把点i放一边不去管它,然后拓扑排序直到不能排为止(入度为0的点(不包括i)都不能在这个时间出现),这个就是最晚时间了

  1 const  2     maxn=2020;  3     maxm=10010;  4 var  5     k,d,first:array[0..maxn]of longint;  6     last,next:array[0..maxm]of longint;  7     n,m,tot:longint;  8   9 procedure insert(x,y:longint); 10 begin 11     inc(tot); 12     last[tot]:=y; 13     next[tot]:=first[x]; 14     first[x]:=tot; 15     inc(d[y]); 16 end; 17  18 var 19     q,kk,du:array[0..maxn]of longint; 20     r:longint; 21  22 procedure swap(var x,y:longint); 23 var 24     t:longint; 25 begin 26     t:=x;x:=y;y:=t; 27 end; 28  29 procedure up(x:longint); 30 var 31     i:longint; 32 begin 33     while x>1 do 34         begin 35             i:=x>>1; 36             if kk[q[x]]>kk[q[i]] then 37                 begin 38                     swap(q[i],q[x]); 39                     x:=i; 40                 end 41             else exit; 42         end; 43 end; 44  45 procedure down(x:longint); 46 var 47     i:longint; 48 begin 49     i:=x<<1; 50     while i<=r do 51         begin 52             if (i<r) and (kk[q[i+1]]>kk[q[i]]) then inc(i); 53             if kk[q[i]]>kk[q[x]] then 54                 begin 55                     swap(q[i],q[x]); 56                     x:=i;i:=x<<1; 57                 end 58             else exit; 59         end; 60 end; 61  62 procedure delete; 63 begin 64     swap(q[1],q[r]); 65     dec(r);down(1); 66 end; 67  68 function time(x:longint):longint; 69 var 70     i:longint; 71 begin 72     time:=n;r:=0; 73     for i:=1 to n do du[i]:=d[i]; 74     for i:=1 to n do kk[i]:=k[i]; 75     for i:=1 to n do 76         if (du[i]=0) and (i<>x) then 77         begin 78             inc(r);q[r]:=i; 79             up(r); 80         end; 81     while r>0 do 82         begin 83             if time>kk[q[1]] then break; 84             kk[q[1]]:=n+1; 85             dec(time); 86             i:=first[q[1]]; 87             while i<>0 do 88                 begin 89                     dec(du[last[i]]); 90                     if (du[last[i]]=0) and (last[i]<>x) then 91                     begin 92                         inc(r);q[r]:=last[i]; 93                         up(r); 94                     end; 95                     i:=next[i]; 96                 end; 97             delete; 98         end; 99     if du[x]<>0 then exit(-1);100 end;101 102 var103     ans:array[0..maxn]of longint;104 105 procedure work;106 var107     i,cnt:longint;108 begin109     r:=0;cnt:=n;110     for i:=1 to n do kk[i]:=k[i];111     for i:=1 to n do du[i]:=d[i];112     for i:=1 to n do113         if du[i]=0 then114         begin115             inc(r);q[r]:=i;116             up(r);117         end;118     while r>0 do119         begin120             ans[cnt]:=q[1];121             dec(cnt);122             i:=first[q[1]];123             kk[q[1]]:=n+1;124             while i<>0 do125                 begin126                     dec(du[last[i]]);127                     if du[last[i]]=0 then128                     begin129                         inc(r);q[r]:=last[i];130                         up(r);131                     end;132                     i:=next[i];133                 end;134             delete;135         end;136     for i:=1 to n do137         if i<n then write(ans[i], )138         else writeln(ans[i]);139 end;140 141 procedure main;142 var143     i,x,y:longint;144 begin145     read(n,m);146     for i:=1 to n do read(k[i]);147     for i:=1 to m do148         begin149             read(x,y);150             insert(y,x);151         end;152     work;153     for i:=1 to n do154         if i<n then write(time(i), )155         else write(time(i));156 end;157 158 begin159     main;160 end.
View Code