#貪心,二叉堆#洛谷 1954 [NOI2010] 航空管制
阿新 • • 發佈:2021-12-21
貪心,二叉堆
分析
首先考慮可行方案,很容易想到拓撲排序,
但是如果建正圖第一類的限制有可能不能滿足,
考慮第一類限制其實時間倒流就是在 \(T\) 時刻之後才能選它。
那麼直接建反圖然後 \(a_i\) 大的優先選,可以用二叉堆來維護。
考慮最早起飛時間那麼將反圖中這個點的後繼全部提出來(正過來看就是這些點是它的祖先)
那麼其它點由於滿足了第一類限制所以順序可以固定,然後將這些後繼包括本身依次合法插入即可
程式碼
#include <cstdio> #include <cctype> #include <algorithm> #include <queue> using namespace std; const int N=2011; priority_queue<pair<int,int> >q; struct node{int y,next;}e[N*5]; int v[N],st[N],n,m,b[N],as[N],a[N],mn[N],ans,tot,upd,deg[N]; int iut(){ int ans=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=ans*10+c-48,c=getchar(); return ans; } void print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } void dfs(int x){ v[x]=upd; for (int i=as[x];i;i=e[i].next) if (v[e[i].y]!=upd) dfs(e[i].y); } int main(){ n=iut(),m=iut(); for (int i=1;i<=n;++i) a[i]=iut(); for (int i=1;i<=m;++i){ int y=iut(),x=iut(); e[i]=(node){y,as[x]},as[x]=i,++deg[y]; } for (int i=1;i<=n;++i) if (!deg[i]) q.push(make_pair(a[i],i)); while (!q.empty()){ int x=q.top().second; st[++st[0]]=x; q.pop(); for (int i=as[x];i;i=e[i].next) if (!(--deg[e[i].y])) q.push(make_pair(a[e[i].y],e[i].y)); } reverse(st+1,st+1+n); for (int i=1;i<=n;++i) print(st[i]),putchar(i==n?10:32); for (int i=1;i<=n;++i){ tot=0,ans=1,++upd,dfs(i); for (int j=1;j<=n;++j) if (v[st[j]]!=upd) b[++tot]=st[j]; mn[tot+1]=0x3f3f3f3f; for (int j=tot;j;--j) mn[j]=min(mn[j+1],a[b[j]]-j); for (int j=1;j<=n-tot;++j) for (;ans<=tot&&mn[ans]<j;++ans); print(ans+n-tot-1),putchar(i==n?10:32); } return 0; }