建一个反图,考虑第 个点最早出现的位置即在反图最晚出现的位置,那么我们先无视这个点,将飞机排序后队列模拟拓扑排序,当无法再进行下去的时候的那个位置即最晚的位置。
第一问就无视 这个点就好了。由于数据保证有解所以贪心原则是正确的。
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;
const ll N=2e3+5;
const ll M=1e4+5;
ll head,tail,q[N];
ll n,m,in[N],lim[N],tmp[N];
ll cnt,to[M],nxt[M],hed[M];
struct node {
ll id,lim;
}a[N];
inline ll read() {
ll x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
bool cmp(node p,node q) {
return p.lim<q.lim;
}
void ins(ll x,ll y) {
to[++cnt]=y;nxt[cnt]=hed[x];hed[x]=cnt;
}
void solve(ll s) {
head=1;tail=0;
memcpy(tmp,in,sizeof(in));
ll p=1;
rep(i,1,n) {
for(;p<=n&&a[p].lim<i;p++) if(!tmp[a[p].id]&&a[p].id!=s) q[++tail]=a[p].id;
if(head<=tail) {
ll x=q[head++];
for(ll j=hed[x];j;j=nxt[j]) {
ll y=to[j];
--tmp[y];
if(!tmp[y]&&y!=s&&lim[y]<i) q[++tail]=y;
}
} else return ;
}
}
int main() {
n=read(),m=read();
rep(i,1,n) {
a[i].id=i;
a[i].lim=read();
a[i].lim=n-a[i].lim;lim[i]=a[i].lim;
}
sort(a+1,a+1+n,cmp);
rep(i,1,m) {
ll x=read(),y=read();
in[x]++;ins(y,x);
}
solve(0);
repd(i,tail,1) printf("%lld%c",q[i],i==1?'\n':' ');
rep(i,1,n) {
solve(i);
printf("%lld ",n-tail);
}
return 0;
}