Input

第一行包含两个正整数n,m,分别表示这家餐厅提供的寿司总数和计算寿司价格中使用的常数。
第二行包含n个正整数,其中第k个数ak表示第k份寿司的代号。
接下来n行,第i行包含n-i+1个整数,其中第j个数di,i+j-1表示吃掉寿司能
获得的相应的美味度,具体含义见问题描述。
N<=100,Ai<=1000

Output

输出共一行包含一个正整数,表示Kiana能获得的总美味度减去花费的总钱数的最大值。

Sample Input

3 1
2 3 2
5 -10 15
-10 15
15

Sample Output

12
分析:看出来这是一道网络流题,却不知道该如何建模......
   看到mx^2 + cx这个式子,我想起了bzoj1449的费用递增模型. 然而m和x都是固定的,每次的增量都是x,费用并不是递增的......
   然后我又想:选取若干个不同的寿司,它们之间会产生贡献. 似乎可以用最小割来做,类似bzoj3144的离散变量模型吗? 这道题选择的寿司之间没有任何限制,当然不是离散变量模型了. 
   单纯考虑最小割可以吗? 每次要求选一段连续的区间不好处理啊.
   上述尝试均失败后,果断打了暴力.
   如果把区间看作点,这道题差不多就做完了. 选择了区间[l,r],则必然会选择在[l,r]中的所有的点,这实际上就是最大权闭合子图模型. 每个区间要向所有区间内的点连边吗? 不用!利用传递关系:[l,r]向[l + 1,r]和[l,r - 1]连边.  当l == r时,就代表了一个点.
   费用要怎么处理呢? 将mx^2 + cx看作mx^2 和 cx两部分. 把编号也看作点. 如果一个编号被选择了,那么它的费用就是mx^2,不会改变.  如果一个点被选择了,那么它的费用就是它的编号.  所以每个编号向T连边,容量为m * i^2. 每个点向其所属的编号连边, 容量为inf.  每个点向T连边,容量为其编号.  这样的话选择了点i,就要割掉它到T的所有连边,即i的编号与T的连边和i与T的连边.
   具体的建图方式如下:

(参考sliverNebula的博客)

    可以这么理解:割掉S与点i的边,就是放弃了i.  割掉i与T的连边,就是选i的代价.

   做网络流的题要有把所有东西都看作“点”的想法.

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; const int maxn = ,maxm = ,inf = 0x7fffffff;
int n,m,a[],mx,d[][],cnt,pos[][],S,T,ans,head[maxn];
int to[maxm],nextt[maxm],w[maxm],tot = ,vis[maxn],cur[maxn]; void add(int x,int y,int z)
{
w[tot] = z;
to[tot] = y;
nextt[tot] = head[x];
head[x] = tot++; w[tot] = ;
to[tot] = x;
nextt[tot] = head[y];
head[y] = tot++;
} bool bfs()
{
queue <int> q;
q.push(S);
memset(vis,-,sizeof(vis));
vis[S] = ;
while (!q.empty())
{
int u = q.front();
q.pop();
if (u == T)
return true;
for (int i = head[u];i;i = nextt[i])
{
int v = to[i];
if (w[i] && vis[v] == -)
{
vis[v] = vis[u] + ;
q.push(v);
}
}
}
return false;
} int dfs(int u,int f)
{
if (u == T)
return f;
int res = ;
for (int i = cur[u];i;i = nextt[i])
{
int v = to[i];
if (w[i] && vis[v] == vis[u] + )
{
int temp = dfs(v,min(f - res,w[i]));
w[i] -= temp;
w[i ^ ] += temp;
res += temp;
if (w[i])
cur[u] = i;
if (res == f)
return res;
}
}
if (!res)
vis[u] = -;
return res;
} void dinic()
{
while (bfs())
{
for (int i = ; i <= T; i++)
cur[i] = head[i];
ans -= dfs(S,inf);
}
} int main()
{
scanf("%d%d",&n,&m);
for (int i = ; i <= n; i++)
{
scanf("%d",&a[i]);
mx = max(mx,a[i]);
}
cnt = mx + n;
for (int i = ; i <= n; i++)
for (int j = i; j <= n; j++)
{
if (i == j)
pos[i][j] = i;
else
pos[i][j] = ++cnt;
}
S = cnt + ;
T = S + ;
for (int i = ; i <= n; i++)
for (int j = ; j <= n - i + ; j++)
{
scanf("%d",&d[i][i + j - ]);
int l = i,r = i + j - ;
if (d[l][r] < )
add(pos[l][r],T,-d[l][r]);
else
{
add(S,pos[l][r],d[l][r]);
ans += d[l][r];
}
if (l != r)
add(pos[l][r],pos[l + ][r],inf),add(pos[l][r],pos[l][r - ],inf);
else
{
add(pos[l][r],a[l] + n,inf);
add(pos[l][r],T,a[l]);
}
}
for (int i = ; i <= mx; i++)
add(i + n,T,i * i * m);
dinic();
printf("%d\n",ans); return ;
}

bzoj4873 [Shoi2017]寿司餐厅的更多相关文章

  1. 【最大权闭合子图】bzoj4873 [Shoi2017]寿司餐厅

    4873: [Shoi2017]寿司餐厅 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 369  Solved: 256[Submit][Status ...

  2. bzoj4873: [Shoi2017]寿司餐厅(最大权闭合子图)

    4873: [Shoi2017]寿司餐厅 大难题啊啊!!! 题目:传送门 题解:一眼题是网络流,但还是不会OTZ,菜啊... %题解... 最大权闭合子图!!! 好的...开始花式建边: 1.对于每个 ...

  3. BZOJ4873[Shoi2017]寿司餐厅——最大权闭合子图

    题目描述 Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个 代号ai和美味度di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无 ...

  4. BZOJ4873 Shoi2017寿司餐厅(最小割)

    选择了某个区间就必须选择其所有子区间,容易想到这是一个最大权闭合子图的模型.考虑将区间按长度分层,相邻层按包含关系连边,区间[i,j]的权值即di,j,其中最后一层表示长度为1的区间的同时也表示寿司本 ...

  5. BZOJ4873 [Shoi2017]寿司餐厅 【最大权闭合子图】

    题目链接 BZOJ4873 题解 题意很鬼畜,就可以考虑网络流[雾] 然后就会发现这是一个裸的最大权闭合子图 就是注意要离散化一下代号 #include<algorithm> #inclu ...

  6. bzoj4873: [Shoi2017]寿司餐厅(最小割)

    传送门 大佬们是怎么一眼看出这是一个最大权闭合子图的……大佬好强->这里 1.把所有区间$(i,j)$看成一个点,如果权值大于0,则从$S$向他连边,容量为权值,否则从它向$T$连边,容量为权值 ...

  7. 【BZOJ4873】[Shoi2017]寿司餐厅 最大权闭合图

    [BZOJ4873][Shoi2017]寿司餐厅 Description Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个代号ai和美味度di ...

  8. BZOJ:4873: [Shoi2017]寿司餐厅

    4873: [Shoi2017]寿司餐厅 首先很开心在膜你赛的时候做了出来. 看到数据范围,看到不能dp,看到贡献去重后计算,咦,流? 那就容易了,转最大权闭合子图,每个区间建一个点,取了就一定要取他 ...

  9. bzoj 4873: [Shoi2017]寿司餐厅 [最小割]

    4873: [Shoi2017]寿司餐厅 题意:略 唯一会做的... 一眼最小割 就是最大权闭合子图呀 \(s\rightarrow d_{positive} \rightarrow -d_{negt ...

随机推荐

  1. Hyperledger Fabric 1.1 -- Policy 构成

    Policy 规则设计 本文主要是讲解一下在fabric中Policy的规则和写法,让大家有一个初步的认识,本文是基于fabric 1.1版本 Policy Type Policy Type 目前包括 ...

  2. 华为笔试——C++转换字符串问题

    题目:转换字符串 题目介绍: 将输入字符串中下标为偶数的字符连成一个新的字符串输出,需要注意两点: 1. 如果输入字符串的长度超过20,则转换失败,返回“ERROR!”字符串: 2. 输入字符串只能由 ...

  3. Amazon Headlines Update on Activity in US West Coast Ports

    According to news reports, freighter cargo may not be offloaded at U.S. West Coast ports from Februa ...

  4. python基础知识-01-编码输入输出变量

    python其他知识目录 名词解释: 编辑器 ide 程序员 操作系统 ASCAII码 unicode utf-8 浅谈CPU.内存.硬盘之间的关系 操作系统及Python解释器工作原理讲解 关于编译 ...

  5. Android源码项目目录结构

    src: 存放java代码 gen: 存放自动生成文件的. R.java 存放res文件夹下对应资源的id project.properties: 指定当前工程采用的开发工具包的版本 libs: 当前 ...

  6. 博弈---ZOJ 2083 Win the Game(染绳子)

    原题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2083 大意:两个人分别对n条绳子染 每次染m长 最后染不下的输,问先 ...

  7. SGU 199 Beautiful People 二维最长递增子序列

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20885 题意: 求二维最长严格递增子序列. 题解: O(n^2) ...

  8. windows(32位 64位)下python安装mysqldb模块

    windows(32位 64位)下python安装mysqldb模块 www.111cn.net 编辑:mengchu9 来源:转载 本文章来给各位使用在此windows系统中的python来安装一个 ...

  9. 转载:java程序调用内存的变化过程

    前文知道了java程序运行时在内存中的大概分布,但是对于具体程序是如何运行的,看到一篇文章,直接转载过来. (一)不含静态变量的java程序运行时内存变化过程分析 代码: package oop; / ...

  10. Spring 学习 3- AOP

    什么是AOP aop就是纵向的编程,业务1和业务2都需要一个共同的操作,与其往每个业务中都添加同样的代码,不如写一遍代码,让两个业务共同使用这段代码. spring中面向切面编程用的是代理模式,它的实 ...