COGS738 [网络流24题] 数字梯形(最小费用最大流)


题目这么说:

给定一个由n 行数字组成的数字梯形如下图所示。梯形的第一行有m 个数字。从梯形
的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶
至底的路径。
规则1:从梯形的顶至底的m条路径互不相交。
规则2:从梯形的顶至底的m条路径仅在数字结点处相交。
规则3:从梯形的顶至底的m条路径允许在数字结点相交或边相交。

对于给定的数字梯形,分别按照规则1,规则2,和规则3 计算出从梯形的顶至底的m
条路径,使这m条路径经过的数字总和最大。

对那三种情况分别建容量网络跑最小费用最大流,这个很容易的。。要注意题意上说的是顶部m个数字分别作为m条路径的出发点。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define INF (1<<30)
  7 #define MAXN 888
  8 #define MAXM 888*888*2
  9 struct Edge{
 10     int u,v,cap,cost,next;
 11 }edge[MAXM];
 12 int head[MAXN];
 13 int NV,NE,vs,vt;
 14 
 15 void addEdge(int u,int v,int cap,int cost){
 16     edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
 17     edge[NE].next=head[u]; head[u]=NE++;
 18     edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
 19     edge[NE].next=head[v]; head[v]=NE++;
 20 }
 21 bool vis[MAXN];
 22 int d[MAXN],pre[MAXN];
 23 bool SPFA(){
 24     for(int i=0;i<NV;++i){
 25         vis[i]=0; d[i]=INF;
 26     }
 27     vis[vs]=1; d[vs]=0;
 28     queue<int> que;
 29     que.push(vs);
 30     while(!que.empty()){
 31         int u=que.front(); que.pop();
 32         for(int i=head[u]; i!=-1; i=edge[i].next){
 33             int v=edge[i].v;
 34             if(edge[i].cap && d[v]>d[u]+edge[i].cost){
 35                 d[v]=d[u]+edge[i].cost;
 36                 pre[v]=i;
 37                 if(!vis[v]){
 38                     vis[v]=1;
 39                     que.push(v);
 40                 }
 41             }
 42         }
 43         vis[u]=0;
 44     }
 45     return d[vt]!=INF;
 46 }
 47 int MCMF(){
 48     int res=0;
 49     while(SPFA()){
 50         int flow=INF,cost=0;
 51         for(int u=vt; u!=vs; u=edge[pre[u]].u){
 52             flow=min(flow,edge[pre[u]].cap);
 53         }
 54         for(int u=vt; u!=vs; u=edge[pre[u]].u){
 55             edge[pre[u]].cap-=flow;
 56             edge[pre[u]^1].cap+=flow;
 57             cost+=flow*edge[pre[u]].cost;
 58         }
 59         res+=cost;
 60     }
 61     return res;
 62 }
 63 int a[22][44],idx[22][44];
 64 int main(){
 65     freopen("digit.in","r",stdin);
 66     freopen("digit.out","w",stdout);
 67     int m,n;
 68     scanf("%d%d",&m,&n);
 69     int cnt=0;
 70     for(int i=0; i<n; ++i){
 71         for(int j=0; j<m+i; ++j) scanf("%d",&a[i][j]),idx[i][j]=cnt++;
 72     }
 73     vs=cnt*2; vt=vs+1; NV=vt+1; NE=0;
 74     memset(head,-1,sizeof(head));
 75     for(int i=0; i<n; ++i){
 76         for(int j=0; j<m+i; ++j){
 77             addEdge(idx[i][j],idx[i][j]+cnt,1,-a[i][j]);
 78             if(i==0) addEdge(vs,idx[i][j],1,0);
 79             if(i==n-1) addEdge(idx[i][j]+cnt,vt,1,0);
 80             else{
 81                 addEdge(idx[i][j]+cnt,idx[i+1][j],1,0);
 82                 addEdge(idx[i][j]+cnt,idx[i+1][j+1],1,0);
 83             }
 84         }
 85     }
 86     printf("%d\n",-MCMF());
 87 
 88     vs=cnt*2; vt=vs+1; NV=vt+1; NE=0;
 89     memset(head,-1,sizeof(head));
 90     for(int i=0; i<n; ++i){
 91         for(int j=0; j<m+i; ++j){
 92             addEdge(idx[i][j],idx[i][j]+cnt,INF,-a[i][j]);
 93             if(i==0) addEdge(vs,idx[i][j],1,0);
 94             if(i==n-1) addEdge(idx[i][j]+cnt,vt,INF,0);
 95             else{
 96                 addEdge(idx[i][j]+cnt,idx[i+1][j],1,0);
 97                 addEdge(idx[i][j]+cnt,idx[i+1][j+1],1,0);
 98             }
 99         }
100     }
101     printf("%d\n",-MCMF());
102 
103     vs=cnt*2; vt=vs+1; NV=vt+1; NE=0;
104     memset(head,-1,sizeof(head));
105     for(int i=0; i<n; ++i){
106         for(int j=0; j<m+i; ++j){
107             addEdge(idx[i][j],idx[i][j]+cnt,INF,-a[i][j]);
108             if(i==0) addEdge(vs,idx[i][j],1,0);
109             if(i==n-1) addEdge(idx[i][j]+cnt,vt,INF,0);
110             else{
111                 addEdge(idx[i][j]+cnt,idx[i+1][j],INF,0);
112                 addEdge(idx[i][j]+cnt,idx[i+1][j+1],INF,0);
113             }
114         }
115     }
116     printf("%d",-MCMF());
117     return 0;
118 }

优质内容筛选与推荐>>
1、6个变态的C语言写的Hello World
2、awk学习简介
3、python 绘图工具 matplotlib 入门
4、struts2 hello world
5、常用git命令[个人整理]


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号