您的位置:首页 > 其它

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

2014-06-17 18:57 253 查看
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)都不能在这个时间出现),这个就是最晚时间了

我懒,用堆写的,实际是过不去的,bzoj总时限可以过

const
maxn=2020;
maxm=10010;
var
first,k,d,di,head,suc,ans:array[0..maxn]of longint;
last,next:array[0..maxm]of longint;
n,m,tot:longint;

procedure insert(x,y:longint);
begin
inc(tot);
last[tot]:=y;
next[tot]:=first[x];
first[x]:=tot;
inc(d[y]);
end;

procedure merge(x,y:longint);
begin
if head[x]=0 then
begin
head[x]:=head[y];
exit;
end;
x:=head[x];
while suc[x]<>0 do x:=suc[x];
suc[x]:=head[y];
end;

function time(x:longint):longint;
var
i,v:longint;
begin
for i:=1 to n do di[i]:=d[i];
for i:=1 to n do head[i]:=0;
for i:=1 to n do
if (d[i]=0) and (i<>x) then
begin
suc[i]:=head[k[i]];
head[k[i]]:=i;
end;
time:=n;
while true do
begin
if head[time]=0 then exit;
i:=first[head[time]];
head[time]:=suc[head[time]];
while i<>0 do
begin
dec(di[last[i]]);
if (di[last[i]]=0) and (last[i]<>x) then
begin
if k[last[i]]<time then v:=k[last[i]]
else v:=time;
suc[last[i]]:=head[v];
head[v]:=last[i];
end;
i:=next[i];
end;
merge(time-1,time);
dec(time);
end;
end;

procedure work;
var
i,t,v:longint;
begin
for i:=1 to n do di[i]:=d[i];
for i:=1 to n do head[i]:=0;
for i:=1 to n do
if d[i]=0 then
begin
suc[i]:=head[k[i]];
head[k[i]]:=i;
end;
t:=n;
while t>0 do
begin
ans[t]:=head[t];
i:=first[head[t]];
head[t]:=suc[head[t]];
while i<>0 do
begin
dec(di[last[i]]);
if di[last[i]]=0 then
begin
if k[last[i]]<t then v:=k[last[i]]
else v:=t;
suc[last[i]]:=head[v];
head[v]:=last[i];
end;
i:=next[i];
end;
merge(t-1,t);
dec(t);
end;
end;

procedure main;
var
i,x,y:longint;
begin
read(n,m);
for i:=1 to n do read(k[i]);
for i:=1 to m do
begin
read(x,y);
insert(y,x);
end;
work;
for i:=1 to n-1 do write(ans[i],' ');
writeln(ans
);
for i:=1 to n-1 do write(time(i),' ');
write(time(n));
end;

begin
main;
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: