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

    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):共(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),表示数据组数。
    对于每组数据:
    第一行两个用空格分开的正整数(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

    (N,M le 100000,D le 3)

    Solution

    考试的时候打的(70')做法,即从小到大依次确定可以放置的最前的位置。复杂度(O(n^{2}))
    正解的做法很简单,却并不好像,好像跟NOI2010航空管制很像。
    将图反连,我们从小到大确定每个最前的位置,即在反top序中从小到大最后的位置。我们还是topsort,只是每次取出的点是所有入度为(0)的标号最大的点。这要的贪心 ,我们就可以保证编号小的尽可能的在后面。最后将top序反着输出即可。

    #include<iostream>
    #include<set>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    
    #define maxn (100010)
    int d[maxn],side[maxn],next[maxn*2],toit[maxn*2],ans[maxn],cnt,n,m;
    
    inline void add(int a,int b) { next[++cnt] = side[a]; side[a] = cnt; toit[cnt] = b; ++d[b]; }
    
    struct cmp { inline bool operator ()(const int &a,const int &b) { return a>b; } };
    set <int,cmp> S;
    
    inline bool topsort()
    {
    	int tot = 0;
    	for (int i = 1;i <= n;++i) if (!d[i]) S.insert(i);
    	while (!S.empty())
    	{
    		int now = *S.begin(); S.erase(S.begin());
    		ans[++tot] = now;
    		for (int i = side[now];i;i = next[i]) if (!--d[toit[i]]) S.insert(toit[i]);
    	}
    	return tot == n;
    }
    
    int main()
    {
    	freopen("4010.in","r",stdin);
    	freopen("4010.out","w",stdout);
    	int T; scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%d %d",&n,&m);
    		for (int i = 1,a,b;i <= m;++i) scanf("%d %d",&a,&b),add(b,a);
    		if (!topsort()) printf("Impossible!");
    		else for (int i = n;i;--i) printf("%d ",ans[i]);
    		puts("");	
    		memset(side,0,4*(n+1));
    		memset(d,0,4*(n+1));
    		cnt = 1;
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    燕园笔记之一——穿梭
    openvc学习笔记(1)——简单应用
    匆匆过客
    opencv学习(3)——高斯平滑图像
    为什么(win10系统)电脑上面的鼠标(触摸板)突然用不了?怎么开启和关闭、
    SqlServer自动备份数据库
    CodeSmith批量生成实体类
    XML文件的序列化和反序列化
    AjaxPro的使用
    设计模式之——策略模式
  • 原文地址:https://www.cnblogs.com/mmlz/p/4448729.html
Copyright © 2011-2022 走看看