问题描述

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

输入格式

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

输出格式

输出文件仅包含 D 行,每行 N 个整数,表示最优的菜肴制作顺序,或者“Impossible!“表示无解(不含引号)。

样例输入

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

样例输出

1 5 3 4 2

Impossible!

1 5 2 4 3

说明

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

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

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

解析

一个直观的想法是拓扑排序,为了满足要求会想到求字典序最小的拓扑序。但是,有可能会出现样例3那样,满足了字典序最小却没有做到小的尽可能要求。为了避免后效性,我们可以建反图再跑字典序最大的拓扑排序,就可以做到答案正确。

代码

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define N 100002
using namespace std;
int head[N],ver[N],nxt[N],d[N],l;
int t,n,m,i,ans[N],cnt;
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
void insert(int x,int y)
{
l++;
ver[l]=y;
nxt[l]=head[x];
head[x]=l;
d[y]++;
}
void toposort()
{
priority_queue<int> q;
for(int i=1;i<=n;i++){
if(d[i]==0) q.push(i);
}
while(!q.empty()){
int x=q.top();
q.pop();
ans[++cnt]=x;
for(int i=head[x];i;i=nxt[i]){
int y=ver[i];
d[y]--;
if(d[y]==0) q.push(y);
}
}
}
int main()
{
t=read();
while(t--){
cnt=l=0;
memset(head,0,sizeof(head));
memset(d,0,sizeof(d));
n=read();m=read();
for(i=1;i<=m;i++){
int u=read(),v=read();
insert(v,u);
}
toposort();
if(cnt<n) printf("Impossible!\n");
else{
for(i=n;i>=1;i--) printf("%d ",ans[i]);
puts("");
}
}
}

[洛谷P3243] 菜肴制作的更多相关文章

  1. Luogu P3243 菜肴制作

    Luogu P3243 菜肴制作 神神奇奇的拓扑排序,也就是借这道题学习一下大名鼎鼎的Toposort了-- #include<bits/stdc++.h> #define N 10001 ...

  2. 洛谷P3243 [HNOI2015]菜肴制作——拓扑排序

    题目:https://www.luogu.org/problemnew/show/P3243 正向按字典序拓扑排序很容易发现是不对的,因为并不是序号小的一定先做: 但若让序号大的尽可能放在后面,则不会 ...

  3. 洛谷P3243 [HNOI2015]菜肴制作 拓扑排序+贪心

    正解:拓扑排序 解题报告: 传送门! 首先看到它这个约束就应该要想到拓扑排序辣QwQ 首先想到的应该是用优先队列代替队列,按照节点编号排序 然后也很容易被hack:<5,1> 正解应为5, ...

  4. 洛谷 P3243 [HNOI2015]菜肴制作 题解

    每日一题 day60 打卡 Analysis 这道题一看就感觉是个拓扑排序,但因为按字典序最小的排序会有问题(见第三个样例)主要原因是每次选择有后效性,而从后往前就不会存在这个问题,因为每个子任务都是 ...

  5. 洛谷 P3243 【[HNOI2015]菜肴制作】

    先吐槽一下这个难度吧,评的有点高了,但是希望别降,毕竟这是我能做出来的不多的紫题了(狗头). 大家上来的第一反应应该都是啊,模板题,然后兴高采烈的打了拓补排序的板子,然后搞个小根堆,按照字典序输出就可 ...

  6. 洛谷P3243 [HNOI2015]菜肴制作 (拓扑排序/贪心)

    这道题的贪心思路可真是很难证明啊...... 对于<i,j>的限制(i必须在j之前),容易想到topsort,每次在入度为0的点中选取最小的.但这种正向找是错误的,题目要求的是小的节点尽量 ...

  7. 洛谷 P6775 - [NOI2020] 制作菜品(找性质+bitset 优化 dp)

    题面传送门 好久没写过题解了,感觉几天没写手都生疏了 首先这种题目直接做肯定是有些困难的,不过注意到题目中有个奇奇怪怪的条件叫 \(m\ge n-2\),我们不妨从此入手解决这道题. 我们先来探究 \ ...

  8. 洛谷P1169 棋盘制作(悬线法)

    题目链接:https://www.luogu.org/problemnew/show/P1169 #include<bits/stdc++.h> #define fi first #def ...

  9. 洛谷P1169 棋盘制作【悬线法】【区间dp】

    题目:https://www.luogu.org/problemnew/show/P1169 题意:n*m的黑白格子,找到面积最大的黑白相间的正方形和矩形. 思路:传说中的悬线法!用下面这张图说明一下 ...

随机推荐

  1. Python学习之==>操作Redis

    一.redis简介 1.非关系型数据库 2.数据全部是存在内存里面 3.性能非常好,每秒支持30w次读写 4.可以通过备份数据库,把数据存到磁盘上来实现数据的持久化 二.操作redis 1.strin ...

  2. PHP 验证香港身份证ID号

    /**check hk idcard$id = "K548653A";$xx= check_hkid($id);var_dump($xx);**/function check_hk ...

  3. hibernate 2 一对多、多对一 双向映射

    多对一或一对多中,在多的一方维护关系效率高 一:java实体类 1.Classes.java package cn.gs.ly.school.entity; import java.util.Set; ...

  4. CF 686D. Kay and Snowflake

    给你一个树N个点,再给出Q个询问,问以x为根的子树中,重心是哪个?2≤n≤300000,1≤q≤30000 Sol:从下到上,根据性质做一下.1:如果某个点x,其子树y的大小超过总结点个数一半,则重心 ...

  5. 递归算法之不用乘号的乘法——用位移实现乘法(dart语言实现)

    前两天突发奇想,写一个乘法的实现,但不用乘号*.并测试一下性能如何.因此就有了下面的代码:(本文主要目的是为了玩递归和位移,因此仅限自然数) 首先,标准乘法: int commonMultiplica ...

  6. 用seaborn对数据可视化

    以下用sns作为seaborn的别名 1.seaborn整体布局设置 sns.set_syle()函数设置图的风格,传入的参数可以是"darkgrid", "whiteg ...

  7. 【Qt开发】几个傻不拉几关于char*和const char*的不兼容问题

    1. string转const char* string s ="abc";constchar* c_s = s.c_str(); 2. const char*转string   ...

  8. HTTP 常见相应状态码及含义

    1xx:信息 100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求. 101 Switching Protocols 服务器转换协议:服务器将 ...

  9. [19/05/29-星期三] JavaScript_ 函数的简介

    一.函数的简介 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...

  10. P1311选择客栈

    这是2011年提高组D1T2,是一个绿色的模拟题,不出所料,没写出代码来. 首先输入n个客栈的颜色和最低消费,然后根据“同颜色但不是一个客栈”以及“两个客栈之间必须有一个的最低消费<=p&quo ...