4873: [Shoi2017]寿司餐厅

大难题啊啊!!!

题目:传送门

题解:一眼题是网络流,但还是不会OTZ,菜啊...

    %题解...

   最大权闭合子图!!!

   好的...开始花式建边:

   1、对于每个区间,我们把它看成一个点,按照权值正负连接源点或汇点(最大权闭合子图的套路)

     2、对于所有的寿司类型k[i],各自开一个点,向ed连边,流量为m*k[i]*k[i];

     3、对于1~n的每个寿司,向它的所属类型连边,流量为无限大;再向ed连边,流量为e[i]。

     4、对于所有的区间i~j,向(i+1,j)和(i,j-1)连边,因为区间具有包含性。

    WA了...再%题解...

     漏了第五种情况:

     5、对于所有区间,向区间内所有的点连边,流量为无限大,表示必须选对应的寿司才能选这个区间QWQ

  跑网络流。。。

蒟蒻的代码(丑的一匹,慎点):

 #include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define qread(x)x=read();
using namespace std;
typedef long long LL;
inline int read()
{
int f=,x=;char ch;
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return f*x;
}
struct node
{
int x,y,c,next,other;
}a[];int last[],len;
int st,ed,n,m;
void ins(int x,int y,int c)
{
int k1,k2;
len++;k1=len;
a[len].x=x;a[len].y=y;a[len].c=c;
a[len].next=last[x];last[x]=len; len++;k2=len;
a[len].x=y;a[len].y=x;a[len].c=;
a[len].next=last[y];last[y]=len; a[k1].other=k2;
a[k2].other=k1;
}
int list[],h[];
int head,tail;
bool bfs()
{
memset(h,,sizeof(h));h[st]=;
list[]=st;head=;tail=;
while(head!=tail)
{
int x=list[head];
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]== && a[k].c>)
{
h[y]=h[x]+;
list[tail++]=y;
}
}
head++;
}
if(h[ed]>)return true;
return false;
}
int findflow(int x,int flow)
{
if(x==ed)return flow;
int s=,t;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(h[y]==h[x]+ && a[k].c> && flow>s)
{
t=findflow(y,min(a[k].c,flow-s));
s+=t;
a[k].c-=t;a[a[k].other].c+=t;
}
}
if(s==)h[x]=;
return s;
}
int e[];
int d[][];
int id1[][],id2[];
bool v[];
int jb()
{
memset(v,false,sizeof(v));
LL sum=,cnt=;
for(int i=;i<=n;i++)
for(int j=i;j<=n;j++)
id1[i][j]=++cnt; for(int i=;i<=n;i++)
if(v[e[i]]==)
{
v[e[i]]=true;
id2[e[i]]=++cnt;
} ed=cnt+n+;
memset(v,false,sizeof(v));
for(int i=;i<=n;i++)
if(v[e[i]]==)
{
v[e[i]]=true;
ins(id2[e[i]],ed,m*e[i]*e[i]);//种类的花费,和ed连边
}
for(int i=;i<=n;i++)
{
ins(cnt+i,id2[e[i]],);
ins(cnt+i,ed,e[i]);
}
for(int i=;i<=n;i++)
for(int j=i;j<=n;j++)
{
if(d[i][j]>)
{
sum+=d[i][j];
ins(st,id1[i][j],d[i][j]);
ins(id1[i][j],cnt+i,);
ins(id1[i][j],cnt+j,);
}
else if(d[i][j]<)
{
ins(id1[i][j],ed,-d[i][j]);
ins(id1[i][j],cnt+i,);
ins(id1[i][j],cnt+j,);
}
if(i!=j)
{
ins(id1[i][j],id1[i][j-],);
ins(id1[i][j],id1[i+][j],);
}
}
return sum;
}
int main()
{
qread(n);qread(m);
for(int i=;i<=n;i++)qread(e[i]);
for(int i=;i<=n;i++)
for(int j=i;j<=n;j++)
qread(d[i][j]);
st=;
LL sum=jb();
/*
for(int i=1;i<=len;i++)
if(a[i].x==0)
printf("%d %d\n",a[i].y,a[i].c);
printf("\n");
for(int i=1;i<=len;i++)
if(a[i].y==ed)
printf("%d %d\n",a[i].x,a[i].c);
*/
int ans=;
while(bfs())ans+=findflow(st,);
printf("%lld\n",sum-ans);
return ;
}

bzoj4873: [Shoi2017]寿司餐厅(最大权闭合子图)的更多相关文章

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

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

  2. [BZOJ4873][六省联考2017]寿司餐厅(最大权闭合子图)

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

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

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

  4. [HEOI2017] 寿司餐厅 + 最大权闭合子图的总结

    Description 太长了自己看叭 点这里! Solution 先学一波什么叫最大权闭合子图. 先要明白什么是闭合子图,闭合子图就是给定一个有向图,从中选择一些点组成一个点集V.对于V中任意一个点 ...

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

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

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

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

  7. bzoj4873 [Shoi2017]寿司餐厅

    Input 第一行包含两个正整数n,m,分别表示这家餐厅提供的寿司总数和计算寿司价格中使用的常数. 第二行包含n个正整数,其中第k个数ak表示第k份寿司的代号. 接下来n行,第i行包含n-i+1个整数 ...

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

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

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

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

随机推荐

  1. Ubuntu 常用快捷键

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50285313 1 桌面 快捷键 作用 ...

  2. HDU 4320 Contest 3

    只需A的全部质因数包含在B中即可. #include <iostream> #include <cstdio> #define LL __int64 #include < ...

  3. leetcode第一刷_Reverse Linked List II

    翻转链表绝对是终点项目,应该掌握的,这道题要求的是翻转一个区间内的节点.做法事实上非常相似,仅仅只是要注意判定開始是头的特殊情况,这样head要更新的,还有就是要把翻转之后的尾部下一个节点保存好,要么 ...

  4. cocos2dx-3.0创建Android项目时遇到的错误。

    cocos run -p android出现 文件名称.文件夹名或卷标语法不对 Updated project.properties Updated local.properties Updated ...

  5. Swift基础--定位

    // // ViewController.swift // JieCoreLocation // // Created by jiezhang on 14-10-4. // Copyright (c) ...

  6. selenium的报错信息:selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Compound class names not permitted

    报错信息:selenium.common.exceptions.InvalidSelectorException: Message: invalid selector: Compound class ...

  7. m_Orchestrate learning system---五、学的越多,做的越快

    m_Orchestrate learning system---五.学的越多,做的越快 一.总结 一句话总结: 1.上传的图像文件用input('post.')方法取不到是为什么? 图片不来就这样取不 ...

  8. 把一串数字表示成千位分隔形式——toLocaleString()

    听说你用什么正则?我这有个骚操作了解下.. toLocaleString() 方法可把一个 Number 对象转换为本地格式的字符串. ().toLocaleString('en-US') " ...

  9. 递归进制转换_strrev

    #define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <stdio.h> #include <stri ...

  10. POJ 1990 线段树

    题意: 思路: 线段树 (一棵就够啦 不像树状数组,还得用两棵) 先对v从小到大排序.每回插入的时候当前的v是最大的,只需要统计它到各个坐标的距离就好了. 里面存两个东西: 这个坐标左边的坐标个数和这 ...