题意:

有\(n\)个数\(a_1\cdots a_n\),现要你给出\(k\)个不相交的非降子序列,使得和最大。

思路:

费用流建图,每个点拆点,费用为\(-a[i]\),然后和源点连边,和后面非降的数连边,源点和超级源点连一条容量\(k\)的边,跑费用流。

用\(spfa\)费用流\(TLE\),这里因为不会出现负环,所以用\(Dijkstra\)优化。

代码:

/*******
dijkstra优化费用流模板
*******/ //不能有负环
#include<functional> //C++编译需要头文件
typedef pair<int, int> pii;//first保存最短距离,second保存顶点的编号
struct edge {
int to, cap, cost, rev; //终点,容量(指残量网络中的),费用,反向边编号
edge() {}
edge(int to, int _cap, int _cost, int _rev):to(to), cap(_cap), cost(_cost), rev(_rev) {}
};
int V; //顶点数
int h[maxn]; //顶点的势
int dis[maxn]; //最短距离
int prevv[maxn];//最短路中的父结点
int pree[maxn]; //最短路中的父边
vector<edge> G[maxn]; //图的邻接表 void init(int n) {
V = n;
for(int i = 0; i <= V; ++i) G[i].clear();
}
void addEdge(int from, int to, int cap, int cost){
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
int MCMF(int s, int t, int f, int &flow){ //f为最多能流多少
int res = 0;
for(int i = 0; i < 1 + V; i++) h[i] = 0;
while(f){
priority_queue<pii, vector<pii>, greater<pii> > q;
for(int i = 0; i < 1 + V; i++) dis[i] = INF;
dis[s] = 0; q.push(pii(0, s));
while(!q.empty()) {
pii now = q.top(); q.pop();
int v = now.second;
if(dis[v] < now.first) continue;
for(int i = 0; i < G[v].size(); ++i) {
edge &e = G[v][i];
if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]){
dis[e.to] = dis[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
pree[e.to] = i;
q.push(pii(dis[e.to], e.to));
}
}
}
if(dis[t] == INF) break;
for(int i = 0; i <= V; ++i) h[i] += dis[i];
int d = f;
for(int v = t; v != s; v = prevv[v]) d = min(d, G[prevv[v]][pree[v]].cap);
f -= d; flow += d; res += d * h[t];
for(int v = t; v != s; v = prevv[v]) {
edge &e = G[prevv[v]][pree[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
#include<map>
#include<set>
#include<cmath>
#include<cstdio>
#include<stack>
#include<ctime>
#include<vector>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 5000 + 5;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
using namespace std; //不能有负环
#include<functional> //C++编译需要头文件
typedef pair<int, int> pii;//first保存最短距离,second保存顶点的编号
struct edge {
int to, cap, cost, rev; //终点,容量(指残量网络中的),费用,反向边编号
edge() {}
edge(int to, int _cap, int _cost, int _rev):to(to), cap(_cap), cost(_cost), rev(_rev) {}
};
int V; //顶点数
int h[maxn]; //顶点的势
int dis[maxn]; //最短距离
int prevv[maxn];//最短路中的父结点
int pree[maxn]; //最短路中的父边
vector<edge> G[maxn]; //图的邻接表 void init(int n) {
V = n;
for(int i = 0; i <= V; ++i) G[i].clear();
}
void addEdge(int from, int to, int cap, int cost){
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
int MCMF(int s, int t, int f, int &flow){ //f为最多能流多少
int res = 0;
for(int i = 0; i < 1 + V; i++) h[i] = 0;
while(f){
priority_queue<pii, vector<pii>, greater<pii> > q;
for(int i = 0; i < 1 + V; i++) dis[i] = INF;
dis[s] = 0; q.push(pii(0, s));
while(!q.empty()) {
pii now = q.top(); q.pop();
int v = now.second;
if(dis[v] < now.first) continue;
for(int i = 0; i < G[v].size(); ++i) {
edge &e = G[v][i];
if(e.cap > 0 && dis[e.to] > dis[v] + e.cost + h[v] - h[e.to]){
dis[e.to] = dis[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
pree[e.to] = i;
q.push(pii(dis[e.to], e.to));
}
}
}
if(dis[t] == INF) break;
for(int i = 0; i <= V; ++i) h[i] += dis[i];
int d = f;
for(int v = t; v != s; v = prevv[v]) d = min(d, G[prevv[v]][pree[v]].cap);
f -= d; flow += d; res += d * h[t];
for(int v = t; v != s; v = prevv[v]) {
edge &e = G[prevv[v]][pree[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
int a[maxn];
int main(){
int T;
scanf("%d", &T);
while(T--){
int n, k;
scanf("%d%d", &n, &k);
init(n * 2 + 5);
int s = n * 2 + 1, e = n * 2 + 2;
int ss = n * 2 + 3, se = n * 2 + 4;
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
addEdge(i, i + n, 1, -a[i]);
addEdge(s, i, 1, 0);
addEdge(i + n, e, 1, 0);
}
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
if(a[i] <= a[j])
addEdge(i + n, j, 1, 0);
}
}
addEdge(ss, s, k, 0);
addEdge(e, se, k, 0);
int flow;
printf("%d\n", -MCMF(ss, se, INF, flow));
}
return 0;
}

HDU 6611 K Subsequence(Dijkstra优化费用流 模板)题解的更多相关文章

  1. HDU2686 费用流 模板

    Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  2. 洛谷P4014 分配问题【最小/大费用流】题解+AC代码

    洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...

  3. 洛谷 P4016负载平衡问题【费用流】题解+AC代码

    洛谷 P4016负载平衡问题 P4014 分配问题[费用流]题解+AC代码 负载平衡问题 题目描述 GG 公司有n个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n ...

  4. Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]

    洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...

  5. HDU 4780 Candy Factory(拆点费用流)

    Problem Description   A new candy factory opens in pku-town. The factory import M machines to produc ...

  6. BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)

    题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...

  7. HDU 5988 Coding Contest(浮点数费用流)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5988 题意:在acm比赛的时候有多个桌子,桌子与桌子之间都有线路相连,每个桌子上会有一些人和一些食物 ...

  8. 初识费用流 模板(spfa+slf优化) 餐巾计划问题

    今天学习了最小费用最大流,是网络流算法之一.可以对于一个每条边有一个容量和一个费用(即每单位流的消耗)的图指定一个源点和汇点,求在从源点到汇点的流量最大的前提下的最小费用. 这里讲一种最基础也是最好掌 ...

  9. 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并

    题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...

随机推荐

  1. Nginx基础环境搭建

    1.下载docker toolbox https://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/ 2.选择好安装目录 一路nex ...

  2. 02_Python基础

    2.1 第一条编程语句 print("Hello, Python!") print("To be, or not to be, it's a question." ...

  3. 糊糊的学习笔记--Fiddle抓包

    Fiddle简述 Fiddler是一个http调试代理,它能 够记录所有的你电脑和互联网之间的http通讯,Fiddler 可以也可以让你检查所有的http通讯,设置断点,以及Fiddle 所有的&q ...

  4. LoadRunner监控Centos和Ubuntu资源之服务器配置

    Centos 我用的版本是Centos6.8   首先更新源以及基础操作我就不说了,直接上步骤: Step 1 安装相关程序 执行命令:yum install inetd,这一步是为了安装rstatd ...

  5. (007)每日SQL学习:将字符和数字分离

    with aa as ( select 'sad10' as data from dual union all select 'datf20' as data from dual union all ...

  6. Typora使用与GItHhub图床配置

    Typora使用 (windows) 1 快捷键 1.1 表格 快捷方式:CTRL+T ID name year 1 Oracle 10 2 Mysql 10 3 Postgresql 20 1.2 ...

  7. Excel 一张表最多能装下多少行多少列数据?

    一个工作簿可以装下255张,那么每张工作表可以装下多少行多少列数据呢? 1.任意打开或新建一个Excel文档. 2.在文档中,找到其左上角的"文件"按钮,点击选择"选项& ...

  8. 关于ckfinder上传文件时不能根据结果返回自定义操作问题?

    最近项目中为了便于文件的管理,所以CMS项目中使用到了ckfinder插件,但是在使用的过程中,发现其自带的上传事件,如果上传重名的文件,该工具会自动提示错误,显示上传失败.但是如果想要自己去处理重名 ...

  9. hadoop的Namenode HA原理详解

    为什么要Namenode HA? 1. NameNode High Availability即高可用. 2. NameNode 很重要,挂掉会导致存储停止服务,无法进行数据的读写,基于此NameNod ...

  10. 13.Linux文件存储系统

    1.Linux 系统中的文件存储结构 Linux系统中常见的目录名称以及相应内容 2.系统内核中的udev 设备管理器会自动把硬件名称规范起来,目的是让用户通过设备文件的名字可以猜出设备大致的属性以及 ...