【洛谷P3749】[六省联考2017]寿司餐厅(网络流)
题意:
给出\(n\)份寿司,现可以选取任意多次连续区间内的寿司,对于区间\([l,r]\),那么贡献为\(\sum_{i=l}^r \sum_{j=i}^rd_{i,j}\)(对于相同的\(d_{i,j}\)只会计算一次)。
每种寿司都有一个标签\(a_i\),若选了\(c\)种标签为\(a_i\)的寿司,此时花费\(ma_i^2+ca_i\)。
问最终最大价值为多少。
思路:
(最小割,费用流这两个东西傻傻分不清楚...)
- 因为对于任意一个区间\([l,r]\),其选择过后,内部区间贡献都要算上,并且每种贡献只算一次。这种严格先后关系并且要求不计算重复的问题,考虑最大权闭合子图。
- 我们将每个\(d_{i,j}\)抽象成点来建立有向图,易知\(d_{i,j}\)向\(d_{i+1,j},d_{i,j-1}\)连边,权值即为\(d_{i,j}\)。
- 考虑如何处理\(ma_i^2+ca_i\):对于标签为\(a_i\)的寿司,我们每选一种,会多出\(c_i\);如果选了标签为\(a_i\),那么就会多出\(ma_i^2\)。所以对于每个\(d_{i,i}\),直接向\(a_i\)连边,表示选了之后会有\(ma_i^2\)的贡献;同时,将\(d_{i,i}\)的权值减去\(a_i\),这样即可处理\(ca_i\)。
- 有向图以及每个点的点权知道后,接下来就直接类似于最大权闭合子图那样建边即可。
代码如下:
/*
* Author: heyuhhh
* Created Time: 2019/10/30 12:45:44
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e4 + 5;
#define _S heyuhhh
template <class T>
struct Dinic{
struct Edge{
int v, next;
T flow;
Edge(){}
Edge(int v, int next, T flow) : v(v), next(next), flow(flow) {}
}e[N * 10];
int head[N], tot;
int dep[N];
void init() {
memset(head, -1, sizeof(head)); tot = 0;
}
void adde(int u, int v, T w, T rw = 0) {
e[tot] = Edge(v, head[u], w);
head[u] = tot++;
e[tot] = Edge(u, head[v], rw);
head[v] = tot++;
}
bool BFS(int _S, int _T) {
memset(dep, 0, sizeof(dep));
queue <int> q; q.push(_S); dep[_S] = 1;
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if(!dep[v] && e[i].flow > 0) {
dep[v] = dep[u] + 1;
q.push(v);
}
}
}
return dep[_T] != 0;
}
T dfs(int _S, int _T, T a) {
T flow = 0, f;
if(_S == _T || a == 0) return a;
for(int i = head[_S]; ~i; i = e[i].next) {
int v = e[i].v;
if(dep[v] != dep[_S] + 1) continue;
f = dfs(v, _T, min(a, e[i].flow));
if(f) {
e[i].flow -= f;
e[i ^ 1].flow += f;
flow += f;
a -= f;
if(a == 0) break;
}
}
if(!flow) dep[_S] = -1;
return flow;
}
T dinic(int _S, int _T) {
T max_flow = 0;
while(BFS(_S, _T)) max_flow += dfs(_S, _T, INF);
return max_flow;
}
};
Dinic <int> solver;
int n, m;
int a[105], Id[105][105], F[105][105];
void run(){
solver.init();
int Max = 0;
for(int i = 1; i <= n; i++) {
cin >> a[i];
Max = max(a[i], Max);
}
int cnt = 2;
for(int i = 1; i <= n; i++) {
for(int j = i; j <= n; j++) {
cin >> F[i][j];
Id[i][j] = ++cnt;
}
}
int S = 1, T = 2;
int ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = i; j <= n; j++) {
int cost = F[i][j];
if(i == j) {
if(m) solver.adde(Id[i][j], cnt + a[i], INF);
cost -= a[i];
} else {
solver.adde(Id[i][j], Id[i][j - 1], INF);
solver.adde(Id[i][j], Id[i + 1][j], INF);
}
if(cost > 0) solver.adde(S, Id[i][j], cost), ans += cost;
else solver.adde(Id[i][j], T, -cost);
}
}
for(int i = 1; i <= Max; i++) {
solver.adde(++cnt, T, m * i * i);
}
dbg(1);
ans -= solver.dinic(S, T);
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> m) run();
return 0;
}
【洛谷P3749】[六省联考2017]寿司餐厅(网络流)的更多相关文章
- 洛谷$P3749$ [六省联考2017] 寿司餐厅 网络流
正解:网络流 解题报告: 传送门$QwQ$ 这道题好烦昂,,,就给了好多变量,,,但仔细读一遍题还是能$get$的所以我就不再提取一遍题目大意辣$QwQ$? 显然考虑建两排点,一排收益一排支出然后最小 ...
- 洛谷P3749 [六省联考2017]寿司餐厅
传送门 题解 这几道都是上周llj讲的题,题解也写得十分好了,所以直接贴了几个链接和代码. //Achen #include<algorithm> #include<iostream ...
- P3749 [六省联考2017]寿司餐厅 最小割
\(\color{#0066ff}{ 题目描述 }\) Kiana 最近喜欢到一家非常美味的寿司餐厅用餐. 每天晚上,这家餐厅都会按顺序提供 \(n\) 种寿司,第 \(i\) 种寿司有一个代号 \( ...
- 【BZOJ4873】[六省联考2017]寿司餐厅(网络流)
[BZOJ4873][六省联考2017]寿司餐厅(网络流) 题面 BZOJ 洛谷 题解 很有意思的题目 首先看到答案的计算方法,就很明显的感觉到是一个最大权闭合子图. 然后只需要考虑怎么构图就行了. ...
- 洛谷 P3747 [六省联考2017]相逢是问候 解题报告
P3747 [六省联考2017]相逢是问候 题目描述 \(\text {Informatik verbindet dich und mich.}\) 信息将你我连结. \(B\) 君希望以维护一个长度 ...
- bzoj千题计划265:bzoj4873: [六省联考2017]寿司餐厅
http://www.lydsy.com/JudgeOnline/problem.php?id=4873 选a必选b,a依赖于b 最大权闭合子图模型 构图: 1.源点 向 正美味度区间 连 流量为 美 ...
- [BZOJ4873][六省联考2017]寿司餐厅(最大权闭合子图)
4873: [Shoi2017]寿司餐厅 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 490 Solved: 350[Submit][Status ...
- 洛谷P3750 [六省联考2017]分手是祝愿(期望dp)
传送门 嗯……概率期望这东西太神了…… 先考虑一下最佳方案,肯定是从大到小亮的就灭(这个仔细想一想应该就能发现) 那么直接一遍枚举就能$O(nlogn)$把这个东西给搞出来 然后考虑期望dp,设$f[ ...
- 洛谷P3746 [六省联考2017]组合数问题
题目描述 组合数 C_n^mCnm 表示的是从 n 个互不相同的物品中选出 m 个物品的方案数.举个例子,从 (1;2;3) 三个物品中选择两个物品可以有 (1;2);(1;3);(2;3) 这三种 ...
随机推荐
- 浅谈JS函数防抖及应用场景
[前言] 在工作中,我们可能碰到这样的问题: 用户在搜索的时候,在不停敲字,如果每敲一个字我们就要调一次接口,接口调用太频繁,给卡住了. 用户在阅读文章的时候,我们需要监听用户滚动到了哪个标题,但是每 ...
- alertmanager
alertmanager主要用于接收prometheus发送的告警信息: wget下载,解压, 配置alertmanager.yml,内容如下: 在prometheus文件下添加rules.yml内容 ...
- 【转】基于Bootstrap的超酷jQuery开关按钮插件
基于Bootstrap的超酷jQuery开关按钮插件
- C++ 标准库 std::find 查找
参见:https://en.cppreference.com/w/cpp/algorithm/find 查找指定字符/数字等. #include <iostream> #include & ...
- 关于join的使用
一.join的作用 join() 定义在Thread.java中.join() 的作用:让“主线程”等待“子线程”结束之后才能继续运行. // 主线程 public class Father exte ...
- 14 opencv读取XML
https://blog.csdn.net/A_L_A_N/article/details/83272772 FileStorage类 FileStorage类将各种OpenCV数据结构的数据存储为X ...
- 优秀文章 Swagger
原文:https://www.cnblogs.com/peterYong/p/9569453.html 原文:https://www.cnblogs.com/lhbshg/p/8711604.html
- go tcp通信
----tcp 客户端 package main import ( "net" "fmt" ) func main() { conn,err := net.Di ...
- 【新特性速递】单元格导航(上下左右键,TAB键和ENTER键)
上下左右按键 其实单元格导航(上下左右按键,需要启用表格的ShowSelectedCell属性)一直都存在,只不过之前的版本(v5.5.0)有一些小的BUG. BUG1 比如锁定列存在时,上下左右键只 ...
- 无聊系列 - C#中一些常用类型与java的类型对应关系
昨天在那个.NET转java群里,看到一位朋友在问C#的int 对应java的哪个对象,就心血来潮,打算写一下C#中一些基础性的东西,在java中怎么找. 1. 基础值类型 如:int,long,do ...