1. 程式人生 > >BZOJ 2535:NOI 2010 航空管制

BZOJ 2535:NOI 2010 航空管制

出發 ace push tps fin 技術分享 != using -a

[NOI2010]航空管制

題面請點上面。

首先第一問,我第一想法是把它放到一個小根堆中,然而這是不行的。

正確的思路是,把圖反過來建,然後放到一個大根堆裏去。

至於原因,感性理解一下,正著貪是有後效性,會陷入到局部最優解,而反著貪則是從終點出發,是正確的。

第二問也不難,我們考慮當前這個點,能不動他就不動,直到不動不行了(此時兩種情況,一是堆空了,二是有人起飛時間晚於降落時間),此時就是第二問的答案。

技術分享圖片
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include
<cstdlib> #include<string> #include<cmath> #include<queue> #define SIZE 1000005 #define rint register int using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch==-) f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-0
; return x*f; } inline void write(int x) { if(x<0) putchar(-),x=-x; if(x>9) write(x/10); putchar(x%10+0); return ; } struct node { int id,v; bool operator < (const node &x) const { return x.v>v; } }; int n,m,cnt,in[SIZE],ru[SIZE],ans[SIZE],v[SIZE];
int head[SIZE],nex[SIZE],to[SIZE],total; priority_queue<node> q; inline void link(int x,int y) { to[++total]=y; nex[total]=head[x]; head[x]=total; return ; } inline void solve1() { for(rint i=1;i<=n;++i) in[i]=ru[i]; for(rint i=1;i<=n;++i) if(!in[i]) q.push((node){i,v[i]}); while(q.size()) { int x=q.top().id;q.pop(); ans[++cnt]=x; for(rint i=head[x];i;i=nex[i]) { int y=to[i];--in[y]; if(!in[y]) q.push((node){y,v[y]}); } } } inline int solve2(int k) { while(q.size()) q.pop(); for(rint i=1;i<=n;++i) in[i]=ru[i]; for(rint i=1;i<=n;++i) if(!in[i] && i!=k) q.push((node){i,v[i]}); for(rint c=n;c>=1;--c) { if(!q.size() || q.top().v<c) return c; int x=q.top().id;q.pop(); for(rint i=head[x];i;i=nex[i]) { int y=to[i];--in[y]; if(!in[y] && y!=k) q.push((node){y,v[y]}); } } } int main() { n=read(),m=read(); for(rint i=1;i<=n;++i) v[i]=read(); for(rint i=1;i<=m;++i) { int x=read(),y=read(); link(y,x);++ru[x]; } solve1(); for(rint i=cnt;i>=1;--i) write(ans[i]),cout<<" ";puts(""); for(rint i=1;i<=n;++i) write(solve2(i)),cout<<" "; return 0; }
View Code

BZOJ 2535:NOI 2010 航空管制