BZOJ4010: [HNOI2015]菜肴制作

【传送门:BZOJ4010


简要题意:

  有n道菜,有m个限制条件,每个限制条件输入x,y,表示第x道菜要在第y道菜之前做

  在满足所有限制条件的情况下,编号小的菜要尽早做

  求出满足要求的菜的顺序,如果没有满足要求的则输出Impossible!


题解:

  拓扑排序

  一开始想着将x连向y,然后跑拓扑,输出字典序最小的序列

  结果发现题目并不是要求字典序最小,而是要求较小的尽量靠前

  那就跑逆拓扑序,然后倒着输出就好了

  因为等价于倒着的字典序最大,因为字典序最大相当于小的尽量靠后,即正着的小的尽量靠前。


参考代码:

#include<cstdio>
#include<cstring>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
    int x,y,d,next;
}a[110000];int len,last[110000];
int ru[110000],s[110000];
bool v[110000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
priority_queue<int>q;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        len=0;memset(last,0,sizeof(last));
        memset(ru,0,sizeof(ru));
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            ins(y,x);
            ru[x]++;
        }
        memset(v,true,sizeof(v));
        bool bk=false;
        for(int i=1;i<=n;i++) if(ru[i]==0) q.push(i);
        int t=0; 
        while(q.empty()==0)
        {
            int x=q.top();q.pop();
            s[++t]=x;
            v[x]=false;
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                ru[y]--;
                if(ru[y]==0) q.push(y);
            }
        }
        if(t!=n) printf("Impossible!");
        else for(int i=n;i>=1;i--) printf("%d ",s[i]);
        printf("\n");
    }
    return 0;
}

 

posted @ 2018-04-10 14:43  Star_Feel  阅读(119)  评论(0编辑  收藏  举报