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
",solve(n));
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/9875528.html