zoukankan      html  css  js  c++  java
  • 【网络流24题】数字梯形

    Description

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

    P

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

    Input

    第1 行中有2个正整数m和n(m,n<=20),分别表示数字梯形的第一行有m个数字,共有n 行。
    接下来的n 行是数字梯形中各行的数字。第1 行有m个数字,第2 行有m+1 个数字,…。

    Output

    将按照规则1,规则2,和规则3 计算出的最大数字总和输出,每行一个最大总和。

    Sample Input

    2 5
    2 3
    3 4 5
    9 10 9 1
    1 1 10 1 1
    1 1 10 12 1 1

    Sample Output

    66
    75
    77

    将每个点一分为二,这个点的上的值赋给连接这两个的边的费用,其他边按照题目的要求来连,费用都为0
    题目有三问,就跑三遍最大费用最大流。
    第一问:每条边的容量都为1。
    第二问:拆开的两个点之间的容量为正无穷,与汇点的容量为正无穷。
    第三问:除了源点之外其他边的容量都为正无穷。
    (代码巨吃藕无比)


    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<cmath>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 1999999999
    using namespace std;
    struct data{
      int nex,to,w,c;
    }e[10000],g1[10000],g2[10000],g3[10000];
    int a[30][30],head1[800],head2[800],head3[800],head[800],edge1=-1,edge2=-1,edge3=-1,dis[800],vis[800],pre[800];
    void add1(int from,int to,int w,int c){
      g1[++edge1].nex=head1[from];
      g1[edge1].to=to,g1[edge1].w=w,g1[edge1].c=c;
      head1[from]=edge1;
    }
    void add2(int from,int to,int w,int c){
      g2[++edge2].nex=head2[from];
      g2[edge2].to=to,g2[edge2].w=w,g2[edge2].c=c;
      head2[from]=edge2;
    }
    void add3(int from,int to,int w,int c){
      g3[++edge3].nex=head3[from];
      g3[edge3].to=to,g3[edge3].w=w,g3[edge3].c=c;
      head3[from]=edge3;
    }
    bool SPFA(int s,int t){
      queue<int>q;
      q.push(s);
      memset(dis,127,sizeof(dis));
      memset(pre,0,sizeof(pre));
      int zd=dis[0];
      vis[s]=1;dis[s]=0;
      while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].nex){
          if(e[i].w>0 && dis[e[i].to]>dis[u]+e[i].c){
        dis[e[i].to]=dis[u]+e[i].c;
        pre[e[i].to]=i;
        if(!vis[e[i].to]) vis[e[i].to]=1,q.push(e[i].to);
          }
        }
      }
      if(dis[t]==zd) return 0;
      else return 1;
    }
    int end(int s,int t){
      int p=0,sum=1999999999,ans=0;
      for(int u=t;u!=s;u=e[p^1].to)
        p=pre[u],sum=min(sum,e[p].w);
      for(int u=t;u!=s;u=e[p^1].to){
        p=pre[u];
        e[p].w-=sum;
        e[p^1].w+=sum;
        ans+=sum*e[p].c;
      }
      return ans;
    }
    int solve(int s,int t){
      int flow=0;
      while(SPFA(s,t)) flow+=end(s,t);
      return -flow;
    }
    int main()
    {
      freopen("!.in","r",stdin);
      freopen("!.out","w",stdout);
      memset(head,-1,sizeof(head));
      memset(head1,-1,sizeof(head1));
      memset(head2,-1,sizeof(head2));
      memset(head3,-1,sizeof(head3));
      int n,m;scanf("%d%d",&n,&m);
      int s=0,sum=(n+n+m-1)*m/2,t=(n+n+m-1)*m+1;
      for(int i=1;i<=m;i++)
        for(int j=1;j<n+i;j++){
          scanf("%d",&a[i][j]);
          int s1=(n+n+i-2)*(i-1)/2+j;
          add1(s1,s1+sum,1,-a[i][j]),add1(s1+sum,s1,0,a[i][j]);
          add2(s1,s1+sum,inf,-a[i][j]),add2(s1+sum,s1,0,a[i][j]);
          add3(s1,s1+sum,inf,-a[i][j]),add3(s1+sum,s1,0,a[i][j]);
        }
      for(int i=1;i<=n;i++)
        add1(s,i,1,0),add1(i,s,0,0),add2(s,i,1,0),add2(i,s,0,0),add3(s,i,1,0),add3(i,s,0,0);
      for(int i=1;i<m;i++)
        for(int j=1;j<n+i;j++){
          int s=(n+n+i-1)*i/2+j,s1=(n+n+i-2)*(i-1)/2+j;
          add1(s1+sum,s,1,0),add1(s,s1+sum,0,0);
          add1(s1+sum,s+1,1,0),add1(s+1,s1+sum,0,0);
          add2(s1+sum,s,1,0),add2(s,s1+sum,0,0);
          add2(s1+sum,s+1,1,0),add2(s+1,s1+sum,0,0);
          add3(s1+sum,s,inf,0),add3(s,s1+sum,0,0);
          add3(s1+sum,s+1,inf,0),add3(s+1,s1+sum,0,0);
        }
      for(int i=1;i<n+m;i++){
        int s=(n+n+m-2)*(m-1)/2;
        add1(s+i+sum,t,1,0),add1(t,s+i+sum,0,0);
        add2(s+i+sum,t,inf,0),add2(t,s+i+sum,0,0);
        add3(s+i+sum,t,inf,0),add3(t,s+i+sum,0,0);
      }
      memcpy(e,g1,sizeof(e));
      memcpy(head,head1,sizeof(head));
      printf("%d
    ",solve(s,t));
      memcpy(head,head2,sizeof(head));
      memcpy(e,g2,sizeof(e));
      printf("%d
    ",solve(s,t));
      memcpy(head,head3,sizeof(head));
      memcpy(e,g3,sizeof(e));
      printf("%d
    ",solve(s,t));
    }
  • 相关阅读:
    HTTP 协议详解
    HTTP抓包工具之Fiddler
    C#网络编程(订立协议和发送文件)
    C#编程总结(十)字符转码
    通信协议:HTTP、TCP、UDP
    C# 对象、文件与二进制串(byte数组)之间的转换
    从输入URL 到页面加载完成的过程
    java动手动脑
    大道至简第二章读后感
    《大道至简》第一章 读后感
  • 原文地址:https://www.cnblogs.com/pantakill/p/6613458.html
Copyright © 2011-2022 走看看