zoukankan      html  css  js  c++  java
  • 【网络流24题】No.16 数字梯形问题 (不相交路径 最大费用流)

    【题意】

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

    输入文件示例
    input.txt
    2 5
    2 3
    3 4 5
    9 10 9 1
    1 1 10 1 1
    1 1 10 12 1 1

    输出文件示例
    output.txt
    66
    75
    77

    【分析】

      1、拆点 点边容量都为1

      2、点容量改为INF

      3、边容量改为INF(实际上就是最短路了。。)

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<cmath>
      8 using namespace std;
      9 #define Maxn 1010
     10 #define INF 0xfffffff
     11 
     12 struct node
     13 {
     14     int x,y,f,o,c,next;
     15 }tt[Maxn*Maxn],t[Maxn*Maxn];int len;
     16 int first[Maxn];
     17 
     18 int mymin(int x,int y) {return x<y?x:y;}
     19 int mymax(int x,int y) {return x>y?x:y;}
     20 
     21 void ins(int x,int y,int f,int c)
     22 {
     23     t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c;
     24     t[len].next=first[x];first[x]=len;t[len].o=len+1;
     25     t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c;
     26     t[len].next=first[y];first[y]=len;t[len].o=len-1;
     27 }
     28 
     29 int st,ed;
     30 queue<int > q;
     31 int dis[Maxn],pre[Maxn],flow[Maxn];
     32 bool inq[Maxn];
     33 bool bfs()
     34 {
     35     while(!q.empty()) q.pop();
     36     memset(dis,-1,sizeof(dis));
     37     memset(inq,0,sizeof(inq));
     38     q.push(st);dis[st]=0;flow[st]=INF;inq[st]=1;
     39     while(!q.empty())
     40     {
     41         int x=q.front();
     42         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
     43         {
     44             int y=t[i].y;
     45             if(dis[y]<dis[x]+t[i].c)
     46             {
     47                 dis[y]=dis[x]+t[i].c;
     48                 pre[y]=i;
     49                 flow[y]=mymin(flow[x],t[i].f);
     50                 if(!inq[y])
     51                 {
     52                     inq[y]=1;
     53                     q.push(y);
     54                 }
     55             }
     56         }
     57         inq[x]=0;q.pop();
     58     }
     59     if(dis[ed]==-1) return 0;
     60     return 1;
     61 }
     62 
     63 void output()
     64 {
     65     for(int i=1;i<=len;i+=2)
     66      printf("%d->%d %d %d
    ",t[i].x,t[i].y,t[i].f,t[i].c);
     67     printf("
    ");
     68 }
     69 
     70 int max_flow()
     71 {
     72     int ans=0,sum=0;
     73     while(bfs())
     74     {
     75         sum+=dis[ed]*flow[ed];
     76         ans+=flow[ed];
     77         int now=ed;
     78         while(now!=st)
     79         {
     80             t[pre[now]].f-=flow[ed];
     81             t[t[pre[now]].o].f+=flow[ed];
     82             now=t[pre[now]].x;
     83         }
     84     }
     85     return sum;
     86 }
     87 
     88 int a[25][25],num[25][25];
     89 int m,n,cnt;
     90 
     91 void init()
     92 {
     93     scanf("%d%d",&m,&n);
     94     for(int i=1;i<=n;i++)
     95     {
     96         for(int j=1;j<=m+i-1;j++)
     97         {
     98             num[i][j]=++cnt;
     99             scanf("%d",&a[i][j]);
    100         }
    101     }
    102     len=0;
    103     memset(first,0,sizeof(first));
    104     st=2*cnt+1;ed=st+1;
    105     for(int i=1;i<=n;i++)
    106     {
    107         for(int j=1;j<=m+i-1;j++)
    108         {
    109             ins(num[i][j],num[i][j]+cnt,1,a[i][j]);
    110             if(i<n)
    111             {
    112                 ins(num[i][j]+cnt,num[i+1][j],1,0);
    113                 ins(num[i][j]+cnt,num[i+1][j+1],1,0);
    114             }
    115         }
    116     }
    117     for(int i=1;i<=m;i++) ins(st,i,1,0);
    118     for(int i=cnt-n-m+2;i<=cnt;i++) ins(i+cnt,ed,1,0);
    119 }
    120 
    121 int main()
    122 {
    123     init();
    124     for(int i=1;i<=len;i++) tt[i]=t[i];
    125     int ans;
    126     ans=max_flow();
    127     printf("%d
    ",ans);
    128     for(int i=1;i<=len;i++) t[i]=tt[i];
    129     for(int i=1;i<=n;i++)
    130       for(int j=1;j<=m+i-1;j++)
    131         ins(num[i][j],num[i][j]+cnt,INF,a[i][j]);
    132     for(int i=cnt-n-m+2;i<=cnt;i++) ins(i+cnt,ed,INF,0);
    133     for(int i=1;i<=len;i++) tt[i]=t[i];
    134     // output();
    135     ans=max_flow();
    136     printf("%d
    ",ans);
    137     // return 0;
    138     for(int i=1;i<=len;i++) t[i]=tt[i];
    139     for(int i=1;i<=n;i++)
    140     {
    141         for(int j=1;j<=m+i-1;j++)
    142         {
    143             if(i<n)
    144             {
    145                 ins(num[i][j]+cnt,num[i+1][j],INF,0);
    146                 ins(num[i][j]+cnt,num[i+1][j+1],INF,0);
    147             }
    148         }
    149     }
    150     ans=max_flow();
    151     printf("%d
    ",ans);
    152     return 0;
    153 }
    View Code

    2016-11-06 20:41:45

  • 相关阅读:
    Java List集合
    Java 集合删除重复元素、删除指定元素
    进程和线程
    Java 线程的同步与死锁
    Java 线程的常用操作方法
    Java 多线程实现
    统计分析
    递归方法(回文)
    素数的输出
    动手动脑二
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6036280.html
Copyright © 2011-2022 走看看