bzoj2109: [Noi2010]Plane 航空管制
topsort+贪心比较明显,但是图要反向建,因为可能前面很大后面很小就挂了
开始我的想法是对于每个点二分答案然而TLE,但是实际上我们可以特判一下,对于当前点不管,直到不合法的情况出现才利用这个点并记录答案
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> using namespace std; struct node { int x,y,next; }a[11000];int len,last[2100]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int n,p[2100],RU[2100],ru[2100]; priority_queue<pair<int,int> >q; pair<int,int>tno; int solve(int st) { memcpy(ru,RU,sizeof(ru)); while(!q.empty())q.pop(); for(int i=1;i<=n;i++) if(ru[i]==0&&i!=st)q.push(make_pair(p[i],i)); int tp=n,ans=-1;bool flag=false; while(!q.empty()||!flag) { if(q.empty()){flag=true,ans=tp,tno=make_pair(p[st],st);} else { tno=q.top(); if(tno.first<tp) { if(!flag&&tp<=p[st]){flag=true,ans=tp;tno=make_pair(p[st],st);} else return -1; } else q.pop(); } int x=tno.second; for(int k=last[x];k;k=a[k].next) { int y=a[k].y;ru[y]--; if(ru[y]==0&&y!=st)q.push(make_pair(p[y],y)); } tp--; } if(!flag)ans=tp,tp--; return tp==0?ans:-1; } int main() { freopen("b.in","r",stdin); freopen("b.out","w",stdout); int m,x,y; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&p[i]); len=0;memset(last,0,sizeof(last)); memset(RU,0,sizeof(RU)); for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); ins(y,x);RU[x]++; } if(solve(1)==-1)return 0; for(int i=1;i<n;i++) printf("%d ",solve(i)); printf("%d\n",solve(n)); return 0; }
pain and happy in the cruel world.