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

传送门

大佬们是怎么一眼看出这是一个最大权闭合子图的……大佬好强->这里

1.把所有区间$(i,j)$看成一个点,如果权值大于0,则从$S$向他连边,容量为权值,否则从它向$T$连边,容量为权值的相反数

2.对于区间$(i,j)$,向所有的寿司$i$到$j$连边,表示选这个区间这些寿司必须选

3.对每一个寿司类型$w[i]$,为他们各自开一个点,向$T$连边,容量为$m*w[i]*w[i]$

4.对每一个寿司向他们所属的类型$w[i]$连边,容量为$inf$,向$T$连边,容量为$w[i]$

5.对于所有区间$(i,j)$,向区间$(i-1,j),(i,j-1)$连边,容量$inf$,表示选了大的必须选小的

然后用总收益减去最小割就行了

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<queue>
  6 #define inf 0x3f3f3f3f
  7 #define ll long long
  8 using namespace std;
  9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 10 char buf[1<<21],*p1=buf,*p2=buf;
 11 inline int read(){
 12     #define num ch-‘0‘
 13     char ch;bool flag=0;int res;
 14     while(!isdigit(ch=getc()))
 15     (ch==‘-‘)&&(flag=true);
 16     for(res=num;isdigit(ch=getc());res=res*10+num);
 17     (flag)&&(res=-res);
 18     #undef num
 19     return res;
 20 }
 21 const int N=50005,M=2000005;
 22 int head[N],Next[M],ver[M],edge[M],tot=1;
 23 int dep[N],cur[N],S,T;
 24 queue<int> q;
 25 inline void add(int u,int v,int e){
 26     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
 27     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;
 28 }
 29 bool bfs(){
 30     while(!q.empty()) q.pop();
 31     for(int i=S;i<=T;++i) cur[i]=head[i];
 32     memset(dep,-1,sizeof(dep));
 33     q.push(S),dep[S]=0;
 34     while(!q.empty()){
 35         int u=q.front();q.pop();
 36         for(int i=head[u];i;i=Next[i]){
 37             int v=ver[i];
 38             if(dep[v]<0&&edge[i]){
 39                 dep[v]=dep[u]+1,q.push(v);
 40                 if(v==T) return true;
 41             }
 42         }
 43     }
 44     return false;
 45 }
 46 int dfs(int u,int limit){
 47     if(u==T||!limit) return limit;
 48     int flow=0,f;
 49     for(int i=cur[u];i;i=cur[u]=Next[i]){
 50         int v=ver[i];
 51         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
 52             flow+=f,limit-=f;
 53             edge[i]-=f,edge[i^1]+=f;
 54             if(!limit) break;
 55         }
 56     }
 57     if(!flow) dep[u]=-1;
 58     return flow;
 59 }
 60 int dinic(){
 61     int flow=0;
 62     while(bfs()) flow+=dfs(S,inf);
 63     return flow;
 64 }
 65 int n,m,a[105],mp[105][105],id[105][105],cnt=0;
 66 int idw[1005];bool vis[1005];ll sum=0;
 67 void build(){
 68     S=0;
 69     for(int i=1;i<=n;++i)
 70     for(int j=1;j<=n;++j)
 71     id[i][j]=++cnt;
 72     for(int i=1;i<=n;++i)
 73     if(!vis[a[i]]) vis[a[i]]=1,idw[a[i]]=++cnt;
 74     T=cnt+n+1;
 75     memset(vis,0,sizeof(vis));
 76     for(int i=1;i<=n;++i)
 77     if(!vis[a[i]]) vis[a[i]]=1,add(idw[a[i]],T,m*a[i]*a[i]);
 78     for(int i=1;i<=n;++i)
 79     add(i+cnt,idw[a[i]],inf),add(i+cnt,T,a[i]);
 80     for(int i=1;i<=n;++i)
 81     for(int j=i;j<=n;++j){
 82         if(mp[i][j]>0){
 83             sum+=mp[i][j];
 84             add(S,id[i][j],mp[i][j]);
 85             add(id[i][j],i+cnt,inf);
 86             add(id[i][j],j+cnt,inf);
 87         }
 88         else if(mp[i][j]<0){
 89             add(id[i][j],T,-mp[i][j]);
 90             add(id[i][j],i+cnt,inf);
 91             add(id[i][j],j+cnt,inf);
 92         }
 93         if(i!=j){
 94             add(id[i][j],id[i+1][j],inf);
 95             add(id[i][j],id[i][j-1],inf);
 96         }
 97     }
 98 }
 99 int main(){
100     //freopen("testdata.in","r",stdin);
101     n=read(),m=read();
102     for(int i=1;i<=n;++i) a[i]=read();
103     for(int i=1;i<=n;++i)
104     for(int j=i;j<=n;++j)
105     mp[i][j]=read();
106     build();
107     printf("%lld\n",sum-dinic());
108     return 0;
109 }

原文地址:https://www.cnblogs.com/bztMinamoto/p/9571630.html

时间: 2024-08-24 00:27:51

bzoj4873: [Shoi2017]寿司餐厅(最小割)的相关文章

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

为什么跑得这么慢 Description Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个 代号ai和美味度di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无限的,Kiana也可以无限次 取寿司来吃,但每种寿司每次只能取一份,且每次取走的寿司必须是按餐厅提供寿司的顺序连续的一段,即Kiana 可以一次取走第1,2种寿司各一份,也可以一次取走第2,3种寿司各一份,但不可以一次取走第1,3种寿司.由于餐 厅提供的寿司种类繁多,

bzoj4873 [Shoi2017]寿司餐厅

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4873 [题解] 没看出来是最大权闭合子图模型--要多学习学习qwq 首先区间$[i,j]$依赖于区间$[i+1,j]$和$[i,j-1]$.每个区间$[i,j](i < j)$的权值就是$d_{i,j}$. 特别地,区间$[i, i]$的权值为$d_{i,j} - a_i$(由于花费原因). 区间$[i, i]$还依赖于$a_i$这个点,$a_i$这个点的权值为$-m * a_i * a_

BZOJ:4873: [Shoi2017]寿司餐厅

4873: [Shoi2017]寿司餐厅 首先很开心在膜你赛的时候做了出来. 看到数据范围,看到不能dp,看到贡献去重后计算,咦,流? 那就容易了,转最大权闭合子图,每个区间建一个点,取了就一定要取他的子区间(依赖关系),代价上也很容易用依赖关系搞. 提交完A了就没理,后来同学说我#1了??? #include<cstdio> #include<algorithm> #define MN 40001 using namespace std; int read_p,read_ca,r

Bzoj4873 [SXOI2017]寿司餐厅

Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 64  Solved: 45 Description Kiana最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个 代号ai和美味度di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无限的,Kiana也可以无限次 取寿司来吃,但每种寿司每次只能取一份,且每次取走的寿司必须是按餐厅提供寿司的顺序连续的一段,即Kiana 可以一次取走第1,2种寿

BZOJ 4873 [Shoi2017]寿司餐厅 | 网络流 最大权闭合子图

链接 BZOJ 4873 题解 当年的省选题--还记得蒟蒻的我Day1 20分滚粗-- 这道题是个最大权闭合子图的套路题.严重怀疑出题人就是先画好了图然后照着图编了个3000字的题面.和我喜欢的妹子当年给别人写的情书一样长-- 最大权闭合子图 最大权闭合子图问题:一个有向图中,每个点带有一个权值(有正有负),有向边\(u \to v\)表示选\(u\)必须选\(v\),选出一些点使权值和最大,问权值和最大是多少. 最大权闭合子图的解法:网络流建图,对于每个点\(u\),设权值为\(w_u\),如

BZOJ_4873_[Shoi2017]寿司餐厅_最大权闭合子图

题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4873 分析:我们发现分数正负都有,并且之间有依赖关系,很容易想到最大权闭合子图. 建图: 1.S向正点连边,负点向T连边. 2.选了[i~j]显然要选[i+1~j]和[i~j-1],分别连边. 3.对于i==j的点,向对应的寿司连边. 4.总花费m*x*x+c*x拆成两部分.对于每个代号x,向T连容量为m*x*x的边,c*x这部分我们考虑算f[i][i]时把f[i][i]的值减掉x,当然也可

bzoj千题计划265:bzoj4873: [六省联考2017]寿司餐厅

http://www.lydsy.com/JudgeOnline/problem.php?id=4873 选a必选b,a依赖于b 最大权闭合子图模型 构图: 1.源点 向 正美味度区间 连 流量为 美味度 的边 2.负美味度区间 向 汇点 连 流量为 美味度的绝对值 的边 3.区间[i,j] 向 区间[i+1,j].区间[i,j-1] 连 流量为 inf 的边 4.区间[i,i] 向 寿司i 连 流量为 inf 的边 5.寿司i 向 汇点 连 流量为 寿司代号 的边 6.寿司i 向 它的代号 连

[六省联考2017]寿司餐厅(最小割)

题意 题目 思路 由得到的权值不重复可以看出这是一道最大权闭合子图问题 (反正我是没看出来),即最小割 可以看出,如果得到了权值\(d_{l,r}\),可以且必须得到权值\(d_{x,y},(l\leq x \leq y\leq r)\),必须要花费\([l,r]\)这一区间的代价,于是可以得到建图方法 将一个区间看做一个点 \(d_{l,r}>0\),\(ans\) \(+=d_{l,r}\),\(S\)向它连边,边权为\(d_{l,r}\),割掉这条边表示不选择这个值,产生\(d_{l,r}

BZOJ 4873 寿司餐厅(最大权闭合图 网络流)

寿司餐厅 时间限制: 1 Sec  内存限制: 512 MB提交: 6  解决: 3[提交][状态][讨论版] 题目描述 Kiana 最近喜欢到一家非常美味的寿司餐厅用餐.每天晚上,这家餐厅都会按顺序提供n种寿司,第i种寿司有一个代号 ai和美味度 di,i,不同种类的寿司有可能使用相同的代号.每种寿司的份数都是无限的,Kiana 也可以无限次取寿司来吃,但每种寿司每次只能取一份,且每次取走的寿司必须是按餐厅提供寿司的顺序连续的一段,即 Kiana 可以一次取走第 1,2种寿司各一份,也可以一次