zoukankan      html  css  js  c++  java
  • [HNOI2015]菜肴制作(拓扑排序)

    知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴。 ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予1到N的顺序编号,预估质量最高的菜肴编号为1。

    由于菜肴之间口味搭配的问题,某些菜肴必须在另一些菜肴之前制作,具体的,一共有 M 条形如”i 号菜肴'必须'先于 j 号菜肴制作“的限制,我们将这样的限制简写为<i,j>。

    现在,酒店希望能求出一个最优的菜肴的制作顺序,使得小 A能尽量先吃到质量高的菜肴:

    也就是说,

    (1)在满足所有限制的前提下,1 号菜肴”尽量“优先制作;

    (2)在满足所有限制,1号菜肴”尽量“优先制作的前提下,2号菜肴”尽量“优先制作;

    (3)在满足所有限制,1号和2号菜肴”尽量“优先的前提下,3号菜肴”尽量“优先制作

    (4)在满足所有限制,1 号和 2 号和 3 号菜肴”尽量“优先的前提下,4 号菜肴”尽量“优先制作;

    (5)以此类推。

    例1:共4 道菜肴,两条限制<3,1>、<4,1>,那么制作顺序是 3,4,1,2。

    例2:共5道菜肴,两条限制<5,2>、 <4,3>,那么制作顺序是 1,5,2,4,3。

    例1里,首先考虑 1,因为有限制<3,1>和<4,1>,所以只有制作完 3 和 4 后才能制作 1,而根据(3),3 号又应”尽量“比 4 号优先,所以当前可确定前三道菜的制作顺序是 3,4,1;接下来考虑2,确定最终的制作顺序是 3,4,1,2。

    例 2里,首先制作 1是不违背限制的;接下来考虑 2 时有<5,2>的限制,所以接下来先制作 5 再制作 2;接下来考虑 3 时有<4,3>的限制,所以接下来先制作 4再制作 3,从而最终的顺序是 1,5,2,4,3。 现在你需要求出这个最优的菜肴制作顺序。无解输出”Impossible!“ (不含引号,首字母大写,其余字母小写)

    Solution

    先考虑暴力的做法,我们从一号点开始枚举,从限制一号点的所有点中找到编号最小的点,在从限制它的点中找编号最小的。。。。以此类推。

    于是我们发现这个过程和在反向图上拓扑排序的过程是一样的。

    Code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define N 100002
    using namespace std;
    int t,n,m,du[N],head[N],tot,x,y,ans[N],top;
    struct zzh{
        int n,to;
    }e[N];
    inline void add(int u,int v){
        e[++tot].n=head[u];
        e[tot].to=v;
        head[u]=tot;
    }
    priority_queue<int>q;
    int main(){
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            memset(head,0,sizeof(head));
            memset(du,0,sizeof(du));tot=top=0;
            for(int i=1;i<=m;++i){
                scanf("%d%d",&x,&y);
                add(y,x); du[x]++;
            }
            for(int i=1;i<=n;++i)if(!du[i])q.push(i);
            while(!q.empty()){
               int u=q.top();q.pop();ans[++top]=u;
               for(int i=head[u];i;i=e[i].n){
                   int v=e[i].to;
                   if(!--du[v])q.push(v);
               }
            }
            if(top!=n)printf("Impossible!
    ");
            else{
                for(int i=top;i>=1;--i)printf("%d ",ans[i]);
                printf("
    ");
            } 
        }
        return 0;
    }
  • 相关阅读:
    Bootstrap(2)整体架构
    介绍 Microservice
    Websocket实例
    MYSQL-用户权限的验证过程(转)
    don't touch your phone in any unfamiliar way(转)
    你真的会玩SQL吗?Case的用法(转)
    android模拟器与PC的端口映射(转)
    Java Main如何被执行?(转)
    Linux crontab 命令格式与具体样例
    分享一个3D球面标签云
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9697668.html
Copyright © 2011-2022 走看看