传送门

费用流经典题。


按照题目要求建边。

为了方便我将所有格子拆点,三种情况下容量分别为111,infinfinf,infinfinf,费用都为validi,jval_{id_{i,j}}validi,j​​。

然后从源点向第一排的mmm个点连边,三种情况下容量都为111,费用都为0。

然后从最后一排的m+n−1m+n-1m+n−1个点向汇点连边,三种情况下容量为111,infinfinf,infinfinf,费用都为0。

至于格子之间的路径,三种情况下容量为111,111,infinfinf,费用都为0。

跑三次最大费用流就行了。

代码:

  1. #include<bits/stdc++.h>
  2. #define N 1005
  3. #define M 20005
  4. using namespace std;
  5. inline int read(){
  6. int ans=0;
  7. char ch=getchar();
  8. while(!isdigit(ch))ch=getchar();
  9. while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
  10. return ans;
  11. }
  12. int n,m,id[25][25],a[25][25],tot=0,all=0;
  13. struct edge{int v,next,c,w;};
  14. struct MCMF{
  15. edge e[M<<1];
  16. bool in[N];
  17. int first[N],d[N],flow[N],pos[N],pred[N],cnt,s,t;
  18. inline void init(){memset(first,-1,sizeof(first)),cnt=-1,s=0,t=all*2+1;}
  19. inline void addedge(int u,int v,int c,int w){e[++cnt].v=v,e[cnt].w=w,e[cnt].c=c,e[cnt].next=first[u],first[u]=cnt;}
  20. inline void add(int u,int v,int c,int w){addedge(u,v,c,w),addedge(v,u,0,-w);}
  21. inline bool spfa(){
  22. queue<int>q;
  23. for(int i=0;i<=t;++i)d[i]=-0x3f3f3f3f;
  24. in[s]=1,d[s]=0,pred[t]=-1,flow[s]=0x3f3f3f3f,q.push(s);
  25. while(!q.empty()){
  26. int x=q.front();
  27. q.pop(),in[x]=0;
  28. for(int i=first[x];~i;i=e[i].next){
  29. int v=e[i].v;
  30. if(e[i].c&&d[v]<d[x]+e[i].w){
  31. d[v]=d[x]+e[i].w,flow[v]=min(flow[x],e[i].c),pred[v]=x,pos[v]=i;
  32. if(!in[v])in[v]=1,q.push(v);
  33. }
  34. }
  35. }
  36. return d[t]!=-0x3f3f3f3f;
  37. }
  38. inline int solve(){
  39. int ret=0;
  40. for(int w=t;spfa();w=t){
  41. ret+=d[t]*flow[t];
  42. while(w!=s)e[pos[w]].c-=flow[t],e[pos[w]^1].c+=flow[t],w=pred[w];
  43. }
  44. return ret;
  45. }
  46. }mcmf;
  47. int main(){
  48. m=read(),n=read(),all=(m*2+n-1)*n/2;
  49. for(int i=1;i<=n;++i)for(int j=1;j<=m+i-1;++j)id[i][j]=++tot,a[i][j]=read();
  50. mcmf.init();
  51. for(int i=1;i<=m;++i)mcmf.add(mcmf.s,id[1][i],1,0);
  52. for(int i=1;i<n;++i)for(int j=1;j<=m+i-1;++j){
  53. mcmf.add(id[i][j],id[i][j]+all,1,a[i][j]);
  54. mcmf.add(id[i][j]+all,id[i+1][j],1,0);
  55. mcmf.add(id[i][j]+all,id[i+1][j+1],1,0);
  56. }
  57. for(int i=1;i<=m+n-1;++i)mcmf.add(id[n][i],id[n][i]+all,1,a[n][i]),mcmf.add(id[n][i]+all,mcmf.t,1,0);
  58. printf("%d\n",mcmf.solve());
  59. mcmf.init();
  60. for(int i=1;i<=m;++i)mcmf.add(mcmf.s,id[1][i],1,0);
  61. for(int i=1;i<n;++i)for(int j=1;j<=m+i-1;++j){
  62. mcmf.add(id[i][j],id[i][j]+all,0x3f3f3f3f,a[i][j]);
  63. mcmf.add(id[i][j]+all,id[i+1][j],1,0);
  64. mcmf.add(id[i][j]+all,id[i+1][j+1],1,0);
  65. }
  66. for(int i=1;i<=m+n-1;++i)mcmf.add(id[n][i],id[n][i]+all,0x3f3f3f3f,a[n][i]),mcmf.add(id[n][i]+all,mcmf.t,0x3f3f3f3f,0);
  67. printf("%d\n",mcmf.solve());
  68. mcmf.init();
  69. for(int i=1;i<=m;++i)mcmf.add(mcmf.s,id[1][i],1,0);
  70. for(int i=1;i<n;++i)for(int j=1;j<=m+i-1;++j){
  71. mcmf.add(id[i][j],id[i][j]+all,0x3f3f3f3f,a[i][j]);
  72. mcmf.add(id[i][j]+all,id[i+1][j],0x3f3f3f3f,0);
  73. mcmf.add(id[i][j]+all,id[i+1][j+1],0x3f3f3f3f,0);
  74. }
  75. for(int i=1;i<=m+n-1;++i)mcmf.add(id[n][i],id[n][i]+all,0x3f3f3f3f,a[n][i]),mcmf.add(id[n][i]+all,mcmf.t,0x3f3f3f3f,0);
  76. printf("%d",mcmf.solve());
  77. return 0;
  78. }

2018.10.15 loj#6010. 「网络流 24 题」数字梯形(费用流)的更多相关文章

  1. 2018.10.14 loj#6012. 「网络流 24 题」分配问题(费用流)

    传送门 费用流水题. 依然是照着题意模拟建边就行了. 为了练板子又重新写了一遍费用流. 代码: #include<bits/stdc++.h> #define N 305 #define ...

  2. 2018.10.14 loj#6011. 「网络流 24 题」运输问题(费用流)

    传送门 费用流入门题. 直接按照题意模拟. 把货物的数量当做容量建边. 然后跑一次最小费用流和最大费用流就行了. 代码: #include<bits/stdc++.h> #define N ...

  3. LOJ #6010. 「网络流 24 题」数字梯形

    #6010. 「网络流 24 题」数字梯形   题目描述 给定一个由 n nn 行数字组成的数字梯形如下图所示.梯形的第一行有 m mm 个数字.从梯形的顶部的 m mm 个数字开始,在每个数字处可以 ...

  4. 【刷题】LOJ 6010 「网络流 24 题」数字梯形

    题目描述 给定一个由 \(n\) 行数字组成的数字梯形如下图所示.梯形的第一行有 \(m\) 个数字.从梯形的顶部的 \(m\) 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至 ...

  5. 2018.10.15 loj#6013. 「网络流 24 题」负载平衡(费用流)

    传送门 费用流sb题. 直接从sss向每个点连边,容量为现有物品量. 然后从ttt向每个点连边,容量为最后库存量. 由于两个点之间可以互相任意运送物品,因此相邻的直接连infinfinf的边就行了. ...

  6. Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流)

    Libre 6010「网络流 24 题」数字梯形 (网络流,最大费用最大流) Description 给定一个由n 行数字组成的数字梯形如下图所示.梯形的第一行有m 个数字.从梯形的顶部的m 个数字开 ...

  7. 2018.10.14 loj#6003. 「网络流 24 题」魔术球(最大流)

    传送门 网络流好题. 这道题可以动态建图. 不难想到把每个球iii都拆点成i1i_1i1​和i2i_2i2​,每次连边(s,i1),(i2,t)(s,i_1),(i_2,t)(s,i1​),(i2​, ...

  8. 【刷题】LOJ 6227 「网络流 24 题」最长k可重线段集问题

    题目描述 给定平面 \(\text{xoy}\) 上 \(n\) 个开线段组成的集合 \(\text{I}\) ,和一个正整数 \(k\) ,试设计一个算法. 从开线段集合 \(\text{I}\) ...

  9. [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划

    [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划 试题描述 一个餐厅在相继的 \(N\) 天里,第 \(i\) 天需要 \(R_i\) 块餐巾 \((i=l,2,-,N)\) ...

随机推荐

  1. 2.mybatis实战教程(mybatis in action)之二:以接口的方式编程

    转自:http://www.yihaomen.com/article/java/304.htm 前面一章,已经搭建好了eclipse,mybatis,mysql的环境,并且实现了一个简单的查询. 请注 ...

  2. canal 常用配置

    https://github.com/alibaba/canal/wiki/AdminGuide canal.instance.filter.regex 监控哪些表的正则配置 如下: mysql 数据 ...

  3. How To Pronounce 3-Syllable Phrases

    How To Pronounce 3-Syllable Phrases Share Tweet Share Tagged With: 3-Syllable Learn about the stress ...

  4. 原生nodejs 学习笔记1

    网上许多nodejs教程或书藉都是教你调用第三方模块来编写nodejs应用的,虽然这是非常便捷的,但是封装太厚,你基本一点东西还是没有学到.人家的模块,人家想怎么改就行,可以下一版本就改了接口,你的应 ...

  5. servlet类

    一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...

  6. Appium的inspector使用

    使用inspectot可以对元素进行定位 1.设置appium的Android Settings,点击左上角的安卓图标进入安卓设置,注意设置时不要开启appium 说明: a)Application是 ...

  7. Honeycomb

    Honeycomb http://codeforces.com/gym/102028/problem/F time limit per test 4.0 s memory limit per test ...

  8. 【校招面试 之 C/C++】第20题 C++ STL(二)之Vector

    1.vector的动态增长 当添加元素时,如果vector空间大小不足,则会以原大小的两倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间.vector的空 ...

  9. 获取APP的启动图 -Launch Image

    http://adad184.com/2015/10/15/tips-access-current-launch-image/

  10. [leetcode]228. Summary Ranges区间统计

    Given a sorted integer array without duplicates, return the summary of its ranges. Example 1: Input: ...