当前位置: 首页 > news >正文

[bzoj4010][HNOI2015]菜肴制作_贪心_拓扑排序

菜肴制作 bzoj-4010 HNOI-2015

题目大意:给定一张n个点m条边的有向图,求一个toposort,使得:(1)满足编号为1的点尽量在前;(2)满足(1)的情况下编号为2的点尽量在前,以此类推。

注释:$1\le n,m\le 10^5$,$1\le cases \le 3$。


想法:只需要先求字典序最大toposort,然后逆序输出即可。

简单的证明:字典序最大的toposort是将当前所有解锁的中编号最大的点放在首位,这样1就会自然而然排在最后。自然就会满足所有的条件。

更严格地,我们采用数学归纳法。

奠基:如上文,我们将可能放在1前面的都放在了1前面,逆序输出的话就会使得1的位置是可能情况下最靠前的,即满足(1)。

归纳假设:若前i个条件都会且仅会在最大拓扑序逆序的条件下被满足,那么对于第i+1点,在前i个点都满足题意的时候,当前解锁的点中如果没有i+1,不考虑。

如果有i+1:

当这些点中还有比i+1更小的点,由归纳假设,想满足前i个条件,只能先放比i大的点,所以比i+1小的点我们不理它们。

那么只考虑不小于i+1的点,我们期望满足条件(i+1)。

所以我们将所有比i+1大的点都先放出来,这样会最大限度地使i+1靠前。

直到当前解锁的点中i+1为最大者,我们才将它放出来。

这样的话,因为满足前i个条件的话我们不能解锁小于i+1的点。在这样的情况下我们又将所有可能放在i+1后面的点放在了i+1后面,所以i+1是在满足前i个条件下最靠前的。

这样我们就满足了条件(i+1)。

证毕

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 100010 
using namespace std;
priority_queue<int>q;
int to[N],nxt[N],head[N],tot;
bool vis[N]; int num[N],cnt,ans[N],n,m;
inline void add(int x,int y)
{
    to[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
inline void original()
{
    tot=cnt=0;
    memset(head,0,sizeof head);
    memset(num,0,sizeof num);
    memset(vis,false,sizeof vis);
    while(!q.empty()) q.pop();
}
bool flag;
void toposort()
{
    while(!q.empty())
    {
        int x=q.top(); q.pop();
        ans[++cnt]=x;
        vis[x]=true;
        for(int i=head[x];i;i=nxt[i])
        {
            num[to[i]]--;
            if(!num[to[i]]) q.push(to[i]);
        }
    }
    for(int i=1;i<=n;i++) if(!vis[i]) {flag=false; return; }
}
int main()
{
    int cases; cin >> cases ;
    while(cases--)
    {
        original();
        cin >> n >> m ;
        for(int x,y,i=1;i<=m;i++) scanf("%d%d",&x,&y),add(y,x),num[x]++;
        flag=true;
        for(int i=1;i<=n;i++)
        {
            if(num[i]) continue;
            q.push(i);
        }
        toposort();
        if(flag) for(int i=cnt;i>=1;i--) printf("%d ",ans[i]);
        else printf("Impossible! ");
        puts("");
    }
}
/*
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 
*/

小结大胆假设,小心求证

转载于:https://www.cnblogs.com/ShuraK/p/9397611.html

相关文章:

  • 测试中的单纯性划分
  • JAVA中的协变与逆变
  • bzoj4004: [JLOI2015]装备购买
  • 【iOS-Cocos2d游戏开发】关于CCSpriteSheet报错问题
  • 《C#多线程编程实战》2.7 CountDownEvent
  • linux下安装Bugzilla(二)
  • 2018-8-1 列表的增删改查及元组的基本操作
  • linux下安装Bugzilla(三)
  • mysql sql优化的一些总结
  • linux下安装Bugzilla(四)
  • Centos7 下安装配置tomcat7
  • 【iOS-Cocos2d游戏开发】使用plist文件制作简单精灵
  • linux awk详解
  • HDU 2680 Choose the best route(多起点单终点最短路问题)题解
  • 【iOS-Cocos2d游戏开发】使用Zwoptex生成plist文件
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Laravel Mix运行时关于es2015报错解决方案
  • ReactNative开发常用的三方模块
  • React组件设计模式(一)
  • spark本地环境的搭建到运行第一个spark程序
  • Web Storage相关
  • 闭包--闭包之tab栏切换(四)
  • 从输入URL到页面加载发生了什么
  • 复杂数据处理
  • 讲清楚之javascript作用域
  • 力扣(LeetCode)21
  • 如何设计一个微型分布式架构?
  • 数据可视化之 Sankey 桑基图的实现
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 译米田引理
  • ​人工智能书单(数学基础篇)
  • # centos7下FFmpeg环境部署记录
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #QT(一种朴素的计算器实现方法)
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (三)Honghu Cloud云架构一定时调度平台
  • (十八)三元表达式和列表解析
  • (转)ABI是什么
  • (转载)hibernate缓存
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .net 设置默认首页
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • @data注解_一枚 架构师 也不会用的Lombok注解,相见恨晚
  • @private @protected @public
  • @Responsebody与@RequestBody
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [C语言]——C语言常见概念(1)
  • [ERROR] 不再支持目标选项 5。请使用 7 或更高版本