zoukankan      html  css  js  c++  java
  • 【BZOJ】【4010】【HNOI2015】菜肴制作

    拓扑排序


      这题是要求N个点的一个拓扑序,且满足以下条件:编号1的位置尽可能靠前,在此基础上编号2的位置尽可能靠前……

      

      我看到这题的第一感觉:将拓扑排序用的队列改为优先队列,编号越小越早出来。

      但是连样例都过不了= =因为这样做是【字典序最小】,并不一定满足题目的条件(看样例就知道了,这样其实是早出队的元素编号尽量小,并不完全是编号小的早出队)

      那么怎么搞呢?正着不行还不让我们反着来吗>_>

      将所有边反向!搞逆拓扑序!这次我们让早出队的元素编号越大越好,也就是让编号越小的尽量靠后,因为在原序中靠前,就是在拓扑逆序中靠后。

      然后就AC辣~

      其实蒟蒻也不会证明……感性理解就是:对于编号小的元素,尽可能用编号比他大的进行拖延,让他晚出队,应该是有点贪心的思想吧= =

      证明:http://zyfzyf.is-programmer.com/posts/89618.html

          http://www.cnblogs.com/vb4896/p/4083650.html

    P.S.这应该是这次胡策中最简单的一题了吧……反而放在C题的位置……

     1 /**************************************************************
     2     Problem: 4010
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:820 ms
     7     Memory:4520 kb
     8 ****************************************************************/
     9  
    10 //Huce #7 C
    11 #include<queue>
    12 #include<vector>
    13 #include<cstdio>
    14 #include<cstdlib>
    15 #include<cstring>
    16 #include<iostream>
    17 #include<algorithm>
    18 #define rep(i,n) for(int i=0;i<n;++i)
    19 #define F(i,j,n) for(int i=j;i<=n;++i)
    20 #define D(i,j,n) for(int i=j;i>=n;--i)
    21 using namespace std;
    22  
    23 int getint(){
    24     int v=0,sign=1; char ch=getchar();
    25     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
    26     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
    27     return v*sign;
    28 }
    29 typedef long long LL;
    30 const int N=100010,INF=~0u>>2;
    31 /*******************template********************/
    32 int to[N<<1],next[N<<1],head[N],cnt;
    33 void add(int x,int y){
    34     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt;
    35 }
    36 int n,m,du[N];
    37 void init(){
    38     n=getint(); m=getint();
    39     cnt=0; memset(head,0,sizeof head);
    40     memset(du,0,sizeof du);
    41     int x,y;
    42     F(i,1,m){
    43         x=getint(); y=getint();
    44         swap(x,y);
    45         add(x,y); du[y]++;
    46     }
    47 }
    48 int ans[N],tot;
    49 void solve(){
    50     priority_queue<int>Q;
    51     F(i,1,n) if (!du[i]) Q.push(i);
    52     tot=0;
    53     while(!Q.empty()){
    54         int x=Q.top(); Q.pop();
    55         ans[++tot]=x;
    56         for(int i=head[x];i;i=next[i]){
    57             du[to[i]]--;
    58             if (du[to[i]]==0) Q.push(to[i]);
    59         }
    60     }
    61     if (tot==n) {D(i,tot,1) printf("%d ",ans[i]); puts("");} 
    62     else puts("Impossible!");
    63 }
    64      
    65 int main(){
    66 #ifndef ONLINE_JUDGE
    67     freopen("C.in","r",stdin);
    68 //  freopen("output.txt","w",stdout);
    69 #endif
    70     int T=getint();
    71     while(T--){
    72         init();
    73         solve();
    74     }
    75     return 0;
    76 }
    View Code

    4010: [HNOI2015]菜肴制作

    Time Limit: 5 Sec  Memory Limit: 512 MB
    Submit: 267  Solved: 159
    [Submit][Status][Discuss]

    Description

    知名美食家小 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!” (不含引号,
    首字母大写,其余字母小写) 

    Input

     第一行是一个正整数D,表示数据组数。 

    接下来是D组数据。 
    对于每组数据: 
    第一行两个用空格分开的正整数N和M,分别表示菜肴数目和制作顺序限
    制的条目数。 
    接下来M行,每行两个正整数x,y,表示“x号菜肴必须先于y号菜肴制作”
    的限制。(注意:M条限制中可能存在完全相同的限制) 

    Output

     输出文件仅包含 D 行,每行 N 个整数,表示最优的菜肴制作顺序,或

    者”Impossible!”表示无解(不含引号)。 

    Sample Input

    3
    5 4
    5 4
    5 3
    4 2
    3 2
    3 3
    1 2
    2 3
    3 1
    5 2
    5 2
    4 3

    Sample Output

    1 5 3 4 2
    Impossible!
    1 5 2 4 3

    HINT

     【样例解释】 


    第二组数据同时要求菜肴1先于菜肴2制作,菜肴2先于菜肴3制作,菜肴3先于

    菜肴1制作,而这是无论如何也不可能满足的,从而导致无解。 

    100%的数据满足N,M<=100000,D<=3。 

    Source

    [Submit][Status][Discuss]

      

  • 相关阅读:
    linux 命令——48 watch (转)
    linux 命令——47 iostat (转)
    linux 命令——46 vmstat(转)
    linux 命令——45 free(转)
    linux 命令——44 top (转)
    linux 命令——43 killall(转)
    linux 命令——42 kill (转)
    linux 命令——41 ps(转)
    linux 命令——40 wc (转)
    Java for LeetCode 068 Text Justification
  • 原文地址:https://www.cnblogs.com/Tunix/p/4450995.html
Copyright © 2011-2022 走看看