zoukankan      html  css  js  c++  java
  • 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
    ",-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
    ",-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 }
  • 相关阅读:
    第十六周个人作业
    排球比赛积分程序
    本周个人总结
    本周个人总结
    排球积分规则
    我与计算机
    排球计分(实践)
    观后感
    18周 个人作业
    总结
  • 原文地址:https://www.cnblogs.com/WABoss/p/5378977.html
Copyright © 2011-2022 走看看