补 第三场多校杭电 费用流 K Subsequence
K Subsequence
这个题目是这个人想吃东西,但是他每次吃的都是他的美味值都必须不递减,可以吃k次,问这个最大的美味值是多少。
这个是一个比较明显的费用流,建图也很好建,但是呢,这个题目卡spfa费用流,所以要用dij的费用流。
刚刚是第一种方法,第二种方法就是优化,减少很多边来优化这个复杂度。
因为每次的美味值都必须不递减,
所以比如我们给x建边,w[x]=a 后面我们建比a大的w[y]=b 如果后面有比b大的z位置就不建了x,z 之间的边,因为之后y,z会建边,x,z可以通过 xy,yz 来连接。
所以呢,这样子建边就少了很多条边,
这个之后还有一次很重要的操作,就是每一个拆点之间要建一条 流量为inf 费用 为 0 的边。
这个是为了保持图的连通性,比如k点,k点已经被用过一次了,但是k点之前有一个点还没有用,它可以通过k点与另外一个点相连,
但是k点已经用过了,就不可以再跑了,但是这样是不对的,所以为了保持这个图的连通性,保证答案的正确性,这个k点与它的拆点之间还要连一条边。
这条边容量应该是inf,因为你不能保证k点之前还有多少个点通过k点和k点之后的点连在一起。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
#define inf 0x3f3f3f3f
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + ;
typedef long long ll;
struct edge {
int u, v, c, f, cost;
edge(int u, int v, int c, int f, int cost) :u(u), v(v), c(c), f(f), cost(cost) {}
};
vector<edge>e;
vector<int>G[maxn];
int a[maxn];//找增广路每个点的水流量
int p[maxn];//每次找增广路反向记录路径
int d[maxn];//SPFA算法的最短路
int inq[maxn];//SPFA算法是否在队列中
void init(int n) {
for (int i = ; i <= n; i++)G[i].clear();
e.clear();
}
void addedge(int u, int v, int c, int cost) {
e.push_back(edge(u, v, c, , cost));
e.push_back(edge(v, u, , , -cost));
int m = e.size();
G[u].push_back(m - );
G[v].push_back(m - );
}
bool bellman(int s, int t, int& flow, long long & cost) {
memset(d, 0xef, sizeof(d));
memset(inq, , sizeof(inq));
d[s] = ; inq[s] = ;//源点s的距离设为0,标记入队
p[s] = ; a[s] = INF;//源点流量为INF(和之前的最大流算法是一样的) queue<int>q;//Bellman算法和增广路算法同步进行,沿着最短路拓展增广路,得出的解一定是最小费用最大流
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = ;//入队列标记删除
for (int i = ; i < G[u].size(); i++) {
edge & now = e[G[u][i]];
int v = now.v;
if (now.c > now.f && d[v] < d[u] + now.cost)
//now.c > now.f表示这条路还未流满(和最大流一样)
//d[v] > d[u] + e.cost Bellman 算法中边的松弛
{
d[v] = d[u] + now.cost;//Bellman 算法边的松弛
p[v] = G[u][i];//反向记录边的编号
a[v] = min(a[u], now.c - now.f);//到达v点的水量取决于边剩余的容量和u点的水量
if (!inq[v]) { q.push(v); inq[v] = ; }//Bellman 算法入队
}
}
}
if (d[t] < )return false;//找不到增广路
flow += a[t];//最大流的值,此函数引用flow这个值,最后可以直接求出flow
cost += (long long)d[t] * (long long)a[t];//距离乘上到达汇点的流量就是费用
for (int u = t; u != s; u = e[p[u]].u)//逆向存边
{
e[p[u]].f += a[t];//正向边加上流量
e[p[u] ^ ].f -= a[t];//反向边减去流量 (和增广路算法一样)
}
return true;
}
int MincostMaxflow(int s, int t, long long & cost) {
cost = ;
int flow = ;
while (bellman(s, t, flow, cost));//由于Bellman函数用的是引用,所以只要一直调用就可以求出flow和cost
return flow;//返回最大流,cost引用可以直接返回最小费用
}
int f[maxn], dp[maxn];
int main() {
int w;
scanf("%d", &w);
while (w--) {
int n, k;
scanf("%d%d", &n, &k);
for (int i = ; i <= n; i++) scanf("%d", &f[i]);
int s1 = , s2 = * n + , t1 = * n + , t2 = * n + ;
init(t2);
addedge(s1, s2, k, ); addedge(t1, t2, k, );
for (int i = ; i <= n; i++) {
addedge(i, i + n, , f[i]);
addedge(i, i + n, inf, );
addedge(s2, i, , );
addedge(i + n, t1, , );
}
for (int i = ; i <= n; i++) {
int x = inf;
for (int j = i + ; j <= n; j++) {
if (f[i] <= f[j] && f[j] < x) addedge(i + n, j, , ), x = f[j];
}
}
ll cost = ;
MincostMaxflow(s1, t2, cost);
printf("%lld\n", cost);
}
return ;
}
费用流
补 第三场多校杭电 费用流 K Subsequence的更多相关文章
- 牛客第三场多校 E Sort String
链接:https://www.nowcoder.com/acm/contest/141/E来源:牛客网 Eddy likes to play with string which is a sequen ...
- 牛客第三场多校 H Diff-prime Pairs
链接:https://www.nowcoder.com/acm/contest/141/H来源:牛客网 Eddy has solved lots of problem involving calcul ...
- PACM Team(牛客第三场多校赛+dp+卡内存+打印路径)
题目链接(貌似未报名的不能进去):https://www.nowcoder.com/acm/contest/141/A 题目: 题意:背包题意,并打印路径. 思路:正常背包思路,不过五维的dp很容易爆 ...
- hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)
题意: 一个数字矩阵,可以出发K次,每次可以从右边或者下面走,要求(在收益最大情况下)覆盖全图,不能则输出-1.(规则:每次跳一步的时候若格子数字相等则获得该数字的能量,每跳一步消耗距离的能量).每个 ...
- 2018 Multi-University Training Contest 9 杭电多校第九场 (有坑待补)
咕咕咕了太久 多校博客直接从第三场跳到了第九场orz 见谅见谅(会补的!) 明明最后看下来是dp场 但是硬生生被我们做成了组合数专场…… 听说jls把我们用组合数做的题都用dp来了遍 这里只放了用组 ...
- 可持久化线段树的学习(区间第k大和查询历史版本的数据)(杭电多校赛第二场1011)
以前我们学习了线段树可以知道,线段树的每一个节点都储存的是一段区间,所以线段树可以做简单的区间查询,更改等简单的操作. 而后面再做有些题目,就可能会碰到一种回退的操作.这里的回退是指回到未做各种操作之 ...
- 2018 HDU多校第三场赛后补题
2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...
- 2018 Multi-University Training Contest 1 杭电多校第一场
抱着可能杭电的多校1比牛客的多校1更恐怖的想法 看到三道签到题 幸福的都快哭出来了好吗 1001 Maximum Multiple(hdoj 6298) 链接:http://acm.hdu.edu. ...
- 2018牛客网暑假ACM多校训练赛(第三场)I Expected Size of Random Convex Hull 计算几何,凸包,其他
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round3-I.html 题目传送门 - 2018牛客多校赛第三场 I ...
随机推荐
- Docker-Bridge Network 02 容器与外部通信
本小节介绍bridge network模式下,容器与外部的通信. 1.前言2.容器访问外部2.1 访问外网2.2 原理2.3 一张图总结2.4 抓包3.外部访问容器3.1 创建nginx容器并从外部访 ...
- 【Java】【设计模式 Design Pattern】单例模式 Singleton
什么是设计模式? 设计模式是在大量的实践中总结和理论化之后的最佳的类设计结构,编程风格,和解决问题的方式 设计模式已经帮助我们想好了所有可能的设计问题,总结在这些各种各样的设计模式当中,也成为GOF2 ...
- 【Java】封装、继承、多态
封装 在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部分包装.隐藏起来的方法. 封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代 ...
- 1196F - K-th Path
题目链接: http://codeforces.com/problemset/problem/1196/F 题目大意::无向图,求任意两点第k短的路径 思路:按照边的大小,只保留前K个边,如果不连同的 ...
- Linux相关操作
ssh配置秘钥 连接远程服务器时:需要用户持有“公钥/私钥对”,远程服务器持有公钥,本地持有私钥. 客户端向服务器发出请求.服务器收到请求之后,先在用户的主目录下找到该用户的公钥,然后对比用户发送过来 ...
- 漫谈LiteOS之开发板-LiteOS移植(基于GD32450i-EVAL)
1 为什么移植? 嵌入式设备的芯片型号和外设的差异较大,资源有限.而RTOS无法适配集成所有的驱动,因此会先适配部分开发板,然后通过移植使得适配更多的开发板. 可移植性是嵌入式操作系统与普通操作系统的 ...
- PHP 常用数组的具体运用?常用吗?
在 PHP 中,有三种类型的数组: 数值数组 - 带有数字 ID 键的数组 关联数组 - 带有指定的键的数组,每个键关联一个值 多维数组 - 包含一个或多个数组的数组 看具体实例: 创建数组 < ...
- 最新VMware虚拟机安装Linux系统-CentOS(详细教程)
一.前言 最近有网友反应初学Linx不会安装,找了许多教程不是太全面,总会遇到一些要不是启动不了,要不是连不上网,各种问题,为了让大家能够顺利的安装,小乐写了一个非常详细的教程,让大家少入坑. 二.背 ...
- mac 使用记录
iterm 配合 lrzsz 实现 上传下载
- Hbase详细架构图解
@ 目录 主要组件 数据模型 注意:Hbase是依赖zookeeper和hdfs的,需要启动zk和hdfs. 主要组件 Zookeeper: HBase 通过 Zookeeper 来做 Master ...