[BZOJ 4010] 菜肴制作

Link:

BZOJ 4010 传送门

Solution:

思路挺妙的一题

一看到有先后的约束关系,肯定要拓扑排序

而且对所有的数要求依次最优(不是字典序最小),看起来贪心选最小的就可以了

但从前往后贪心会出现问题:

对于两个数$x,y$,其中$x<y$,如果$y$无约束关系,其会出现在$x$之前

为了解决这样的问题,发现只要反向建边,从后往前拓扑排序同时贪心选取最大的就行了

Code:

//by NewErA
#include <bits/stdc++.h>

using namespace std;

const int MAXN=1e5+5;
int T,n,m,in[MAXN];
vector<int> a[MAXN],res;

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(in,0,sizeof(in));res.clear();
        for(int i=0;i<MAXN;i++) a[i].clear();

        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            a[y].push_back(x);in[x]++;
        }
        priority_queue<int> que;
        for(int i=1;i<=n;i++)
            if(!in[i]) que.push(i);
        while(!que.empty())
        {
            int v=que.top();que.pop();res.push_back(v);
            for(int i=0;i<a[v].size();i++)
            {
                in[a[v][i]]--;
                if(!in[a[v][i]]) que.push(a[v][i]);
            }
        }
        
        if(res.size()!=n) puts("Impossible!");
        else
        {
            reverse(res.begin(),res.end());
            for(int i=0;i<res.size();i++) printf("%d ",res[i]);
            puts("");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/newera/p/9138912.html