热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

洛谷P2050[NOI2012]美食节

如果没有做过修车(本题的弱化版),可以先去做一下。大致思路就是把每个厨师拆成\(p\)个点,分别代表倒数第几个做哪道菜,然后从每种菜向厨师连边,倒数第几个的边权就是几倍的等待时间,

如果没有做过修车(本题的弱化版),可以先去做一下。

大致思路就是把每个厨师拆成\(p\)个点,分别代表倒数第几个做哪道菜,然后从每种菜向厨师连边,倒数第几个的边权就是几倍的等待时间,最后跑一波费用流即可。

但本题的数据范围有些残酷,所以我们考虑动态加边。最多只会跑\(p\)次\(spfa\),并且每次走最短路增广,所以很多边都是没有用的。首先把代表倒数第一个做的菜的边加上。然后,比如某一次跑完\(spfa\)后,是沿第\(j\)个厨师的倒数第\(k\)个增广的,那就把他的代表倒数\(k+1\)的边补全。

代码如下:

#include
using namespace std;
#define N 40
#define M 100
#define P 800
#define SZ (N+P*M)
#define pb push_back
#define INF 0x3f3f3f3f
struct Edge
{
int from, to, cap, cost;
};
int n, m, tot, S, T, ans, ans0, t[N+5], d[SZ+5], vis[SZ+5], a[SZ+5], pre[SZ+5], tim[M+5][N+5], lim[M+5];
vector G[SZ+5];
vector edges;
int ID(int j, int k)
{
return n+(j-1)*tot+k;
}
int rev(int id)
{
return (id-n-1)/tot+1;
}
void addEdge(int u, int v, int cap, int cost)
{
edges.pb(Edge{u, v, cap, cost}), edges.pb(Edge{v, u, 0, -cost});
G[u].pb(edges.size()-2), G[v].pb(edges.size()-1);
}
int spfa()
{
memset(d, 0x3f, sizeof d);
d[S] = 0, vis[S] = 1, a[S] = INF, pre[S] = 0;
queue q; q.push(S);
while(!q.empty())
{
int u = q.front(); q.pop();
vis[u] = 0;
for(int i = 0, v, w; i {
Edge &e = edges[G[u][i]]; v = e.to, w = e.cost;
if(e.cap > 0 && d[v] > d[u]+w)
{
d[v] = d[u]+w;
a[v] = min(a[u], e.cap);
pre[v] = G[u][i];
if(!vis[v]) q.push(v), vis[v] = 1;
}
}
}
if(d[T] == INF) return 0;
int u = T;
ans0 += a[T], ans += d[T]*a[T];
while(u != S)
{
edges[pre[u]].cap -= a[T], edges[pre[u]^1].cap += a[T];
u = edges[pre[u]].from;
}
return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("testdata.in", "r", stdin);
freopen("testdata.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
S = 0;
for(int i = 1; i <= n; ++i) scanf("%d", &t[i]), tot += t[i], addEdge(S, i, t[i], 0);
T = n+tot*m+1;
for(int i = 1; i <= n; ++i)
{
for(int j = 1, t; j <= m; ++j) scanf("%d", &tim[j][i]), addEdge(i, ID(j, 1), 1, tim[j][i]), lim[j] = 1;
}
for(int i = n+1; i <= n+tot*m; ++i) addEdge(i, T, 1, 0);
while(spfa())
{
int j = rev(edges[pre[T]].from);
lim[j]++;
for(int i = 1; i <= n; ++i) addEdge(i, ID(j, lim[j]), 1, lim[j]*tim[j][i]);
}
printf("%d\n", ans);
return 0;
}


推荐阅读
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • hlg_oj_1116_选美大赛这题是最长子序列,然后再求出路径就可以了。开始写的比较乱,用数组什么的,后来用了指针就好办了。现在把代码贴 ... [详细]
  • 线段树详解与实现
    本文详细介绍了线段树的基本概念及其在编程竞赛中的应用,并提供了一个具体的线段树实现代码示例。 ... [详细]
  • 网络流24题——试题库问题
    题目描述:假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算 ... [详细]
  • 本问题涉及在给定的无向图中寻找一个至少包含三个节点的环,该环上的节点不重复,并且环上所有边的长度之和最小。目标是找到并输出这个最小环的具体方案。 ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • 本文详细介绍了如何在循环双链表的指定位置插入新元素的方法,包括必要的步骤和代码示例。 ... [详细]
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
  • 探讨了一个包含纯虚函数的C++代码片段,分析了其中的语法错误及逻辑问题,并提出了修正方案。 ... [详细]
  • 本文深入探讨了Go语言中的接口型函数,通过实例分析其灵活性和强大功能,帮助开发者更好地理解和运用这一特性。 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • 本文通过分析一个具体的案例,探讨了64位Linux系统对32位应用程序的兼容性问题。案例涉及OpenVPN客户端在64位系统上的异常行为,通过逐步排查和代码测试,最终定位到了与TUN/TAP设备相关的系统调用兼容性问题。 ... [详细]
  • 在Qt框架中,信号与槽机制是一种独特的组件间通信方式。本文探讨了这一机制相较于传统的C风格回调函数所具有的优势,并分析了其潜在的不足之处。 ... [详细]
  • 本文档介绍了如何使用ESP32开发板在STA模式下实现与TCP服务器的通信,包括环境搭建、代码解析及实验步骤。 ... [详细]
  • 本文介绍了如何在不同操作系统上安装Git,以及一些基本和高级的Git操作,包括项目初始化、文件状态检查、版本控制、分支管理、标签处理、版本回退等,并简要提及了开源许可协议的选择。 ... [详细]
author-avatar
手机用户2602913391
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有