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. SQL行列乾坤大挪移

    “生活总是这样,有时候,你需要一个苹果,但别人却给了你一个梨.” 今天dalao邮件里需要添加一张每月累计长长的图,可是,拿到手上的SQL导出数据不符合我最爱的pyecharts的数据输入格式,头大. ...

  2. Python基础灬列表&字典生成式

    列表生成式 # 求1~10偶数的平方 # 1.常规写法 a_list = [] for i in range(1, 11): if i % 2 == 0: a_list.append(i * i) p ...

  3. spring-boot-mybatis搭建

    写在开始 mybatis是一个持久化框架,支持手动sql.存储过程.高级映射.mybatis支持XML方式或注解方式将POJO与数据库表间建立映射. maven依赖 spring-boot.mysql ...

  4. Scrum立会报告+燃尽图(十一月二十一日总第二十九次):β阶段第二周分配任务

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2284 项目地址:https://git.coding.net/zhang ...

  5. Scrum立会报告+燃尽图(十月十七日总第八次):分配Alpha阶段任务

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2246 项目地址:https://git.coding.net/zhang ...

  6. Android数据储存之SQLiteDatabase 简单增删改查

    SQLiteDatabase 使用 SQLiteDatabase提供如下方法来打开一个文件对应的数据库: openDatabase(String path, SQLiteDatabase.Cursor ...

  7. 第一个scrum会议

    第一阶段冲刺任务认领: PM薛哥: 让手电筒亮起来 梁哥: 代码测试 康哥: 用户反馈等等

  8. 博弈--ZOJ 3084 S-Nim(SG)

    题意: 首先输入K 表示一个集合的大小  之后输入集合 表示对于这对石子只能去这个集合中的元素的个数 之后输入 一个m 表示接下来对于这个集合要进行m次询问  之后m行 每行输入一个n 表示有n个堆  ...

  9. vs调试iisExpress经常卡死

    最近调试一个项目时,电脑经常卡死,不得不强制重启,一直不知道iisExpress为何卡死的. 想了很多办法,强制删除bin里面的文件,结果不行: 企图删除iisExpress虚拟目录中的文件也不行: ...

  10. JavaWeb应用的生命周期

    JavaWeb应用的生命周期是由Servlet容器来控制. 启动阶段 (1)读取web.xml配置文件数据 (2)为JavaWeb应用创建一个ServletContext对象 (3)对所有的Filte ...