HDU 6611 K Subsequence(Dijkstra优化费用流 模板)题解
题意:
有\(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优化费用流 模板)题解的更多相关文章
- HDU2686 费用流 模板
Matrix Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 洛谷P4014 分配问题【最小/大费用流】题解+AC代码
洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...
- 洛谷 P4016负载平衡问题【费用流】题解+AC代码
洛谷 P4016负载平衡问题 P4014 分配问题[费用流]题解+AC代码 负载平衡问题 题目描述 GG 公司有n个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n ...
- Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]
洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...
- HDU 4780 Candy Factory(拆点费用流)
Problem Description A new candy factory opens in pku-town. The factory import M machines to produc ...
- BZOJ.3638.CF172 k-Maximum Subsequence Sum(模拟费用流 线段树)
题目链接 各种zz错误..简直了 /* 19604kb 36292ms 题意:选$k$段不相交的区间,使其权值和最大. 朴素线段树:线段树上每个点维护O(k)个信息,区间合并时O(k^2),总O(mk ...
- HDU 5988 Coding Contest(浮点数费用流)
http://acm.split.hdu.edu.cn/showproblem.php?pid=5988 题意:在acm比赛的时候有多个桌子,桌子与桌子之间都有线路相连,每个桌子上会有一些人和一些食物 ...
- 初识费用流 模板(spfa+slf优化) 餐巾计划问题
今天学习了最小费用最大流,是网络流算法之一.可以对于一个每条边有一个容量和一个费用(即每单位流的消耗)的图指定一个源点和汇点,求在从源点到汇点的流量最大的前提下的最小费用. 这里讲一种最基础也是最好掌 ...
- 【bzoj3638】Cf172 k-Maximum Subsequence Sum 模拟费用流+线段树区间合并
题目描述 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. 输入 The first line contains inte ...
随机推荐
- Java优先队列PriorityQueue的各种打开方式以及一些你不知道的细节
目录 Java优先队列PriorityQueue的各种打开方式以及一些你不知道的细节 优先队列的默认用法-从小到大排序 对String类用优先队列从大到小排序 通过自定义比较器对自定义的类进行从小到大 ...
- std::thread线程库详解(3)
目录 目录 前言 lock_guard scoped_lock (C++17) unique_lock shared_lock 总结 ref 前言 前两篇的博文分别介绍了标准库里面的线程和锁,这一次的 ...
- Django前后端分离项目部署
vue+drf的前后端分离部署笔记 前端部署过程 端口划分: vue+nginx的端口 是81 vue向后台发请求,首先发给的是代理服务器,这里模拟是nginx的 9000 drf后台运行在 9005 ...
- Tensorflow-基础使用
Tensorflow基本概念 使用图(graphs)来表示计算任务 在被称之为会话(Session)的上下文(context)中执行图 使用tensor表示数据 通过变量(Variable)维护状态 ...
- Android 开发学习进程0.27 kotlin使用 和viewbinding的使用
kotlin-android-extensions 插件被废弃 笔者曾经尝试写过一部分的kotlin代码 主要是项目中一些代码是kotlin完成的,其中我认为 kotlin的kotlin-androi ...
- linux编译模块,包含了头文件却还是报undifind警告
在编写一个自己写的gadget驱动的时候遇到一个这样的问题,编译的时候报了个警告:WARNING: "usb_composite_register" [-/my_zero.ko] ...
- kotlin和python哪个好!程序员怎样优雅度过35岁中年危机?满满干货指导
导语 学历永远是横在我们进人大厂的一道门槛,好像无论怎么努力,总能被那些985,211 按在地上摩擦! 不仅要被"他们"看不起,在HR挑选简历,学历这块就直接被刷下去了,连证明自己 ...
- Python+Selenium+Unittest实现PO模式web自动化框架(1)
1.什么是PO模式? PO是Page Object的缩写 PO模式是自动化测试项目开发实践的最佳设计模式之一,讲页面定位和业务操作分开,也就是把对象的定位和测试脚本分开,从而提供可维护性. 主要有以下 ...
- Jmeter的Cookie管理器调试与参数化
默认系统都是需要登录,才能操作其它接口,所以需要添加一个HTTP Cookie 管理器,默认Cookie管理器是关闭的,需要修改jmeter配置文件jmeter.properties,该文件在jme ...
- 向HDFS中指定的文件追加内容,由用户指定内容追加到原有文件的开头或结尾。
1 import java.io.FileInputStream; 2 import java.io.IOException; 3 import java.text.SimpleDateFormat; ...