BZOJ4873[Shoi2017]寿司餐厅——最大权闭合子图
题目描述
输入
输出
输出共一行包含一个正整数,表示Kiana能获得的总美味度减去花费的总钱数的最大值。
点权有正有负,点权计算不重复,选了某些点就必须选其他点。可以看出是最大权闭合子图,用正点权和减掉最小割就能得出答案。
那么怎么建图?
由题目可看出总共有三种点:代号、区间美味度、寿司。
结合三者的关系连边:
1、对于所有区间,如果美味度为正,从源点连过来,如果美味度为负,连到汇点,美味度转正。
2、对于所有区间(i,j),连向(i+1,j)和(i,j-1),容量为INF,表示要选小区间之后才能选大区间。
3、对于所有区间(i,j),连向i和j,容量为INF,表示选了对应寿司才能选这个区间(因为第二种连边,所以不用把i到j所有寿司都连上)。
4、对于所有寿司,连向它们对应代号,容量为INF;连向汇点,容量为a[i]。
5、对于所有代号,连向汇点,容量为为m*a[i]*a[i]。
连完边直接跑最大流就行了。这是我认为最好的一道最大流的题,难点就在于如何建图,建明白图后这道题就能迎刃而解了。
最后附上代码。
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int next[100001];
int to[100001];
int val[100001];
int head[100001];
int tot=1;
int q[100001];
int n,m;
int S,T;
int s[120][120];
int vis[1010];
int w[1010];
int a[120];
int id[120][120];
long long ans;
long long sum;
int cnt;
int d[100001];
const int INF=0x3f3f3f3f;
void add(int x,int y,int v)
{
tot++;
next[tot]=head[x];
head[x]=tot;
to[tot]=y;
val[tot]=v;
tot++;
next[tot]=head[y];
head[y]=tot;
to[tot]=x;
val[tot]=0;
}
bool bfs(int S,int T)
{
int r=0;
int l=0;
memset(d,-1,sizeof(d));
q[r++]=S;
d[S]=0;
while(l<r)
{
int now=q[l];
for(int i=head[now];i;i=next[i])
{
if(d[to[i]]==-1&&val[i]!=0)
{
d[to[i]]=d[now]+1;
q[r++]=to[i];
}
}
l++;
}
if(d[T]==-1)
{
return false;
}
else
{
return true;
}
}
int dfs(int x,int flow)
{
if(x==T)
{
return flow;
}
int now_flow;
int used=0;
for(int i=head[x];i;i=next[i])
{
if(d[to[i]]==d[x]+1&&val[i]!=0)
{
now_flow=dfs(to[i],min(flow-used,val[i]));
val[i]-=now_flow;
val[i^1]+=now_flow;
used+=now_flow;
if(now_flow==flow)
{
return flow;
}
}
}
if(used==0)
{
d[x]=-1;
}
return used;
}
void dinic()
{
while(bfs(S,T)==true)
{
ans+=dfs(S,INF);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
scanf("%d",&s[i][j]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
id[i][j]=++cnt;
}
}
for(int i=1;i<=n;i++)
{
if(!vis[a[i]])
{
vis[a[i]]=1;
w[a[i]]=++cnt;
}
}
S=0;
T=cnt+n+1;
memset(vis,0,sizeof vis);
for(int i=1;i<=n;i++)
{
if(!vis[a[i]])
{
vis[a[i]]=1;
add(w[a[i]],T,m*a[i]*a[i]);
}
}
for(int i=1;i<=n;i++)
{
add(cnt+i,T,a[i]);
add(cnt+i,w[a[i]],INF);
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
if(s[i][j]>0)
{
sum+=s[i][j];
add(S,id[i][j],s[i][j]);
add(id[i][j],cnt+i,INF);
add(id[i][j],cnt+j,INF);
}
else if(s[i][j]<0)
{
add(id[i][j],T,-s[i][j]);
add(id[i][j],cnt+i,INF);
add(id[i][j],cnt+j,INF);
}
if(i!=j)
{
add(id[i][j],id[i+1][j],INF);
add(id[i][j],id[i][j-1],INF);
}
}
}
dinic();
sum-=ans;
printf("%lld",sum);
return 0;
}
BZOJ4873[Shoi2017]寿司餐厅——最大权闭合子图的更多相关文章
- [BZOJ4873][六省联考2017]寿司餐厅(最大权闭合子图)
4873: [Shoi2017]寿司餐厅 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 490 Solved: 350[Submit][Status ...
- 【BZOJ4873】[Shoi2017]寿司餐厅 最大权闭合图
[BZOJ4873][Shoi2017]寿司餐厅 Description Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个代号ai和美味度di ...
- [HEOI2017] 寿司餐厅 + 最大权闭合子图的总结
Description 太长了自己看叭 点这里! Solution 先学一波什么叫最大权闭合子图. 先要明白什么是闭合子图,闭合子图就是给定一个有向图,从中选择一些点组成一个点集V.对于V中任意一个点 ...
- 【最大权闭合子图】bzoj4873 [Shoi2017]寿司餐厅
4873: [Shoi2017]寿司餐厅 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 369 Solved: 256[Submit][Status ...
- bzoj4873: [Shoi2017]寿司餐厅(最大权闭合子图)
4873: [Shoi2017]寿司餐厅 大难题啊啊!!! 题目:传送门 题解:一眼题是网络流,但还是不会OTZ,菜啊... %题解... 最大权闭合子图!!! 好的...开始花式建边: 1.对于每个 ...
- BZOJ4873 [Shoi2017]寿司餐厅 【最大权闭合子图】
题目链接 BZOJ4873 题解 题意很鬼畜,就可以考虑网络流[雾] 然后就会发现这是一个裸的最大权闭合子图 就是注意要离散化一下代号 #include<algorithm> #inclu ...
- bzoj4873 [Shoi2017]寿司餐厅
Input 第一行包含两个正整数n,m,分别表示这家餐厅提供的寿司总数和计算寿司价格中使用的常数. 第二行包含n个正整数,其中第k个数ak表示第k份寿司的代号. 接下来n行,第i行包含n-i+1个整数 ...
- BZOJ4873 Shoi2017寿司餐厅(最小割)
选择了某个区间就必须选择其所有子区间,容易想到这是一个最大权闭合子图的模型.考虑将区间按长度分层,相邻层按包含关系连边,区间[i,j]的权值即di,j,其中最后一层表示长度为1的区间的同时也表示寿司本 ...
- bzoj4873: [Shoi2017]寿司餐厅(最小割)
传送门 大佬们是怎么一眼看出这是一个最大权闭合子图的……大佬好强->这里 1.把所有区间$(i,j)$看成一个点,如果权值大于0,则从$S$向他连边,容量为权值,否则从它向$T$连边,容量为权值 ...
随机推荐
- 牛客网 Python 编程输入规范
import sys try: while True: line = sys.stdin.readline().strip() if line == '': break lines = line.sp ...
- ElasticSearch 分组查询的几个例子
facets接口可以根据query返回统计数据,其中的 terms_stats 是分组统计,根据key的情况返回value的统计数据,类似group by的意思. "terms_stats& ...
- Vue2 实现树形菜单(多级菜单)功能模块
结构示意图 ├── index.html ├── main.js ├── router │ └── index.js # 路由配置文件 ├── components # 组件目录 │ ├── App. ...
- 使用HDTune规避硬盘上损坏的扇区
如何使用HDTune扫描磁盘上的错误在网上已经有很多帖子了,但扫描到之后如何用HDTune来规避硬盘上损坏的扇区呢? HDTune并不能直接规避,而是需要重新划分磁盘的卷.HDTune一行有50个小方 ...
- Golang中进行reslice时的注意事项
先看下面代码: package main import "fmt" func main() { slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8} ...
- bootstrap 弹窗或者提示框插件 bootstrap-growl 和bootstrap-notify
Bootstrap简单好用的页面右上角咆哮提示框 - daidaineteasy的专栏 - CSDN博客https://blog.csdn.net/daidaineteasy/article/deta ...
- react 路由4 学习
表单控件 受控表单组件 非受控的表单组件 demo:收集表单提交的数据 路由(V4) 特点:一切皆是组件 官网:https://reacttraining.com/react-router/ npm ...
- Velocity中判断是否为空
方法一: 使用 #ifnull() 或 #ifnotnull() eg:#ifnull ($foo) 要使用这个特性必须在velocity.properties文件中加入: userdirective ...
- 编写自己的composer项目
编写自己的composer项目 composer的出现给php开发带来极大的便利, 配合phpunit的测试工具, 也可以更好的规范php开发. 尽管这些标准不是官方提供的, 但现在大部分的php ...
- Windows10 等 administrator 打开IE 或者edge的方法
gpedit.msc 组策略处理即可