BZOJ P2109&2535 「NOI2010」航空管制【贪心】【拓扑排序】

建一个反图,考虑第 i i 个点最早出现的位置即在反图最晚出现的位置,那么我们先无视这个点,将飞机排序后队列模拟拓扑排序,当无法再进行下去的时候的那个位置即最晚的位置。

第一问就无视 0 0 这个点就好了。由于数据保证有解所以贪心原则是正确的。

#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;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/82930212