首页 > 代码库 > BZOJ 2109 航空管制(拓扑排序+贪心)

BZOJ 2109 航空管制(拓扑排序+贪心)

绝世好题啊。。

题意:给出一个DAG,和每个点要求出现在这个DAG里面的拓扑排序的位置<=ti,求出所有可能的拓扑排序里面每个点出现的位置的最小值。

 

正着做不好做,考虑反着做,建立这个图的反图。

对于一个点出现的位置的最小值,就是n-这个点在反图中出现的位置的最大值。

也就是说拓扑排序时尽量把这个点i排在后面就行了。但是还需要满足一个限制,在反图中这个限制就是每个点在拓扑排序的位置>=n-ti。

于是我们每次拓扑排序从队列中取出点的时候,尽量取n-ti值最小的点,这样就能尽量使得当前处理的点i排在尽可能后的位置。

用一个小根堆实现。因此总的时间复杂度就是O(n^2logn).

 

技术分享
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-8
# define MOD 30031
# define INF 1000000000
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<1,l,mid
# define rch p<<1|1,mid+1,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
const int N=2005;
//Code begin...

int dee[N], d[N], ans[N], t[N];
VI E[N];
struct qnode{
    int v, c;
    qnode(int _v=0, int _c=0):v(_v),c(_c){}
    bool operator<(const qnode &r)const{return c>r.c;}
};
priority_queue<qnode>Q;
int main ()
{
    int n, m, u, v, num;
    qnode tmp;
    scanf("%d%d",&n,&m);
    FOR(i,1,n) scanf("%d",t+i), t[i]=n-t[i];
    while (m--) scanf("%d%d",&u,&v), E[v].pb(u), ++dee[u];
    FOR(i,1,n) {
        num=0;
        FOR(j,1,n) {
            d[j]=dee[j];
            if (d[j]==0&&j!=i) Q.push(qnode(j,t[j]));
        }
        while (!Q.empty()) {
            tmp=Q.top(); Q.pop();
            if (tmp.c>num) break;
            ++num;
            FO(j,0,E[tmp.v].size()) {
                --d[E[tmp.v][j]];
                if (d[E[tmp.v][j]]==0&&E[tmp.v][j]!=i) Q.push(qnode(E[tmp.v][j],t[E[tmp.v][j]]));
            }
        }
        ans[i]=n-num;
        while (!Q.empty()) Q.pop();
    }
    FOR(i,1,n) printf("%d ",ans[i]);
    putchar(\n);
    return 0;
}
View Code

 

BZOJ 2109 航空管制(拓扑排序+贪心)