唉,人蠢就是没办法。。。
首先第一问和菜肴制作类似,考虑正这做,然后放入k的小根堆中会有后效性。。
所以拓扑反序后,放入k的大根堆中,然后从后往前贪心的取即可。
考虑第二问,数据范围能够承受对于每一个点单独处理,其实这一问不是很难,可能硬是有点蠢。。。
我们对于当前这个点,能不取他就不取他(即放着他不管),直到不满足条件为止(直到堆为空,或者有人的起飞时间比最晚时间要晚)
至于正确性的证明我也不会。。。
// MADE BY QT666 #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> using namespace std; typedef long long ll; const int N=200050; const int Inf=19260817; struct data{ int x,k; bool operator < (const data &a) const{ return k<a.k; } }; priority_queue<data> q; int n,m,in[N],deg[N],k[N],ans[N]; int head[N],to[N],nxt[N],cnt; void lnk(int x,int y){ to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt; } void top_sort(int g){ while(!q.empty()) q.pop(); for(int i=1;i<=n;i++){ deg[i]=in[i]; if(i==g) deg[i]=Inf; if(!deg[i]) q.push((data){i,k[i]}); } for(int id=n;id;id--){ if(q.empty()){ans[g]=id;return;} data x=q.top();q.pop(); if(x.k<id) {ans[g]=id;return;} for(int i=head[x.x];i;i=nxt[i]){ int y=to[i];deg[y]--; if(!deg[y]) q.push((data){y,k[y]}); } } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&k[i]); for(int i=1;i<=m;i++){ int u,v;scanf("%d%d",&u,&v); lnk(v,u);in[u]++; } for(int i=1;i<=n;i++) top_sort(i); for(int i=1;i<n;i++) printf("%d ",ans[i]); printf("%d",ans[n]); return 0; }
bzoj 2109: [Noi2010]Plane 航空管制
原文:http://www.cnblogs.com/qt666/p/7231374.html