您的位置:首页 > 其它

bzoj 2109: [Noi2010]Plane 航空管制 贪心+拓扑排序

2017-11-02 20:03 225 查看

题意

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

n≤2,000,m≤10,000。

分析

对于一个第二种限制(a,b),考虑从b向a连一条有向边。那么一个合法的序列肯定是满足拓扑序倒序的。

假设我们现在要求第x辆飞机的答案,考虑把该图做拓扑排序,那么如果一个点度为0且其时间限制不小于当前时间,则该点可以被加入队列,否则就等到该点可以被使用的时候再把该点加入。

由于x要尽量靠后,那么我们就一直不使用x,知道某一时刻队列为空则该时刻即为答案。

为什么要反着建边呢?因为第一个限制限制的是最晚时间,那么如果从后往前选,就不用担心时间限制冲突的问题了。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int N=2005;

int n,m,cnt,last
,q
,d
,t
,degree
;
struct edge{int to,next;}e[N*5];
vector<int> vec
;

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;
}

void addedge(int u,int v)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
}

int solve(int tar)
{
for (int i=1;i<=n;i++) vec[i].clear(),d[i]=degree[i];
int head=1,tail=0;
for (int i=1;i<=n;i++)
if (!d[i]&&i!=tar)
{
if (t[i]==n) q[++tail]=i;
else vec[t[i]].push_back(i);
}
int tim=n+1;
while (1)
{
tim--;
for (int i=0;i<vec[tim].size();i++) q[++tail]=vec[tim][i];
vec[tim].clear();
if (head>tail) return tim;
int u=q[head];head++;
for (int i=last[u];i;i=e[i].next)
{
d[e[i].to]--;
if (!d[e[i].to]&&e[i].to!=tar)
{
if (t[e[i].to]>=tim) q[++tail]=e[i].to;
else vec[t[e[i].to]].push_back(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();
addedge(y,x);degree[x]++;
}
for (int i=1;i<=n;i++) printf("%d ",solve(i));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: