题意:

有\(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. Java 给Word不同页面设置不同背景

    Word文档中,可直接通过[设计]-[页面颜色]页面颜色,通过Java代码可参考如下设置方法: 1. 设置单一颜色背景 doc.getBackground().setType(BackgroundTy ...

  2. 为什么要使用 do while(0)?

    两点 避免宏定义的花括号对代码的完整性造成影响 可以在指定的代码块中(do{})使用break提前跳出,避免goto.

  3. .Vue-router跳转和location.href有什么区别

    使用location.href='/url'来跳转,简单方便,但是刷新了页面:使用history.pushState('/url'),无刷新页面,静态跳转:引进router,然后使用router.pu ...

  4. 使用jiffies的时间比较函数time_after、time_before

    1. jiffies简介 首先,操作系统有个系统专用定时器(system timer),俗称滴答定时器,或者系统心跳. 全局变量jiffies取值为自操作系统启动以来的时钟滴答的数目,在头文件< ...

  5. LOJ2436

    题目描述 幼儿园里有 N 个小朋友, lxhgww 老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于 ...

  6. 3D运动类申明与实现

    #ifndef PKM3D_H #define PKM3D_H #include"kinematics.h" #include"Inventor/Qt/viewers/S ...

  7. Golang 版的ssh爆破小工具

    源码如下: package main import ( "bufio" "flag" "fmt" "golang.org/x/cr ...

  8. Node 使用webpack编写简单的前端应用

    编写目的 1. 使用 Node 依赖webpack.jQuery编写简单的前端应用. 操作步骤 (1)新建一个目录 $ mkdir simple-app-demo $ cd simple-app-de ...

  9. 十二:SpringBoot-基于Cache注解模式,管理Redis缓存

    SpringBoot-基于Cache注解模式,管理Redis缓存 1.Cache缓存简介 2.核心API说明 3.SpringBoot整合Cache 3.1 核心依赖 3.2 Cache缓存配置 3. ...

  10. Think in Java 第三章操作符

    Think in Java 第三章操作符 赋值 对象赋值 ​ 我们真正操作的是对对象的引用.所以倘若"将一个对象赋值给另一个对象",实际上是将"引用"从一个地方 ...