738. [Network Flow 24 questions] digital Ladder «Problem Description:
Given a number of n-line numbers, the trapezoid is shown in the following figure. The first line of the trapezoid has a m number. From trapezoid
The top of the m number starts, at each number can be moved in the lower left or lower right direction, forming a ladder from the top
The path to the bottom.
Rule 1: The M-Path from the top of the trapezoid to the bottom of the ladder is disjoint.
Rule 2: The M-Path from the top to bottom of the ladder intersects only the digital nodes.
Rule 3: The M-Path from the top to bottom of the trapezoid allows intersection of the digital nodes or edges.
«Programming Tasks:
For a given number of trapezoidal, respectively, according to Rule 1, Rule 2, and rule 3 to calculate the top-to-bottom m from the trapezoid
Path so that the number of numbers passing through the M-Path is the largest.
«Data Entry:
The input data is provided by the file digit.in. The 1th line of the file has 2 positive integers m and n (m,n<=20), respectively
Indicates that the first line of the digital ladder has m numbers, and there are n rows. The next n rows are the numbers of the rows in the digital ladder.
The 1th line has m numbers, the 2nd line has m+1 numbers, ....
«Result Output:
At the end of the program run, the sum of the maximum numbers calculated by rule 1, Rule 2, and rule 3 is output to the file
The digit.out. One maximum sum per line.
Example output file for input file sample
Digit.in
2 5
2 3
3 4 5
9 10 9 1
1 1 10) 1 1
1 1 10 12 1 1
Digit.out
66
75
77
This problem is three of network flow synthesis integrated. The difficulty is decreasing.
<1> for the first rule, because it needs not to intersect, you want to split the point . Split I into IA and IB, then IA and IB with a flow rate of 1, the cost is the value of I side. Next, an edge with a flow rate of 1 and a cost of 0 is attached to a ib,ja that conforms to the moving rules from top to bottom. Then, from the virtual source point to each point in the first row, each point in the last row to the virtual meeting point, a point with a flow rate of 1 and a cost of 0 , respectively.
<2> for the second rule, because you can intersect vertices, you do not need to split the points . A value of j is connected directly between the I,J, which conforms to the moving rules from top to bottom, with a flow rate of 1 . Then, from the virtual source point to each point in the first row with a flow of 1, the cost is the value of I . Finally, from each point in the last row to the virtual meeting point, a point with an infinite flow and a cost of 0 .
<3> for the third rule, because there is no limit , it can be directly on the basis of the <2> change a place , that is, in accordance with the move rules from top to bottom of the i,j between a flow is infinite, the cost of the value of J . The rest is the same as <2>.
Code:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath
> #include <algorithm> #define N 100010 #define INF 0x7fffffff using namespace std;
struct edge{int v,next,res,cost;
inline void NewEdge () {v=next=res=cost=0;
}}edge[n];
int n,m,num=1,ans,tot,sum,s,t,map[51][51];
int flow[n],prep[n],prev[n],dis[n],g[n],que[10*n];
BOOL Vis[n];
inline int in () {int x=0; char Ch=getchar ();
while (ch< ' 0 ' | | ch> ' 9 ') Ch=getchar ();
while (ch>= ' 0 ' && ch<= ' 9 ') x=x*10+ch-' 0 ', Ch=getchar ();
return x;
} inline void Add (int u,int v,int cap,int cost) {edge[++num].v=v; edge[num].next=g[u]; g[u]=num; Edge[num].res=cap;
Edge[num].cost=cost;
} inline void Clean () {for (int i=1; i<=num; i++) Edge[i].newedge (); memset (G,0,sizeof (g));
Num=1;
} inline bool Spfa () {int h=0,t=1;
memset (dis,0x7f,sizeof (dis));
memset (vis,false,sizeof (VIS)); dis[s]=0; Vis[s]=true;
Prep[s]=-1; Flow[s]=inf;
Que[0]=s; while (h<t) {iNT u=que[h++];
Vis[u]=false;
for (int i=g[u]; i; i=edge[i].next) {int v=edge[i].v;
if (edge[i].res>0 && dis[v]>dis[u]+edge[i].cost) {dis[v]=dis[u]+edge[i].cost; Prep[v]=u;
Prev[v]=i;
Flow[v]=min (Flow[u],edge[i].res);
if (!vis[v]) vis[v]=true,que[t++]=v;
}}} if (DIS[T]>0X7FFFFFF) return false;
for (int i=t; i!=s; I=prep[i]) {edge[prev[i]].res-=flow[t];
EDGE[PREV[I]^1].RES+=FLOW[T];
} Ans+=flow[t]*dis[t];
return true;
} inline void Work1 () {ans=tot=0;
for (int i=1, i<=n; i++) for (int j=1; j<=m+i-1; J + +) {tot++;
Add (Tot,tot+sum,1,-map[i][j]), add (Tot+sum,tot,0,map[i][j]);
} tot=0;
for (int i=1, i<n; i++) for (int j=1; j<=m+i-1; J + +) {tot++; int k= (2*m+i-1) * (I/2) + (i%2==0? 0:m+ (I/2));
Add (tot+sum,k+j,1,0), add (k+j,tot+sum,0,0);
Add (tot+sum,k+j+1,1,0), add (k+j+1,tot+sum,0,0);
} for (int i=1; i<=m; i++) Add (s,i,1,0), add (i,s,0,0); for (int i=1; i<=m+n-1; i++) Add (2*sum-m-n+i+1,t,1,0), add(t,2*sum-m-n+i+1,0,0);
while (SPFA ());
printf ("%d\n",-ans); } inline void Work2 () {ans=tot=0; s=0; t=sum+1;
Clean ();
for (int i=1, i<n; i++) for (int j=1; j<=m+i-1; J + +) {tot++; int k= (2*m+i-1) * (I/2) + (i%2==0? 0:m+ (I/2));
Add (Tot,k+j,1,-map[i+1][j]), add (K+j,tot,0,map[i+1][j]);
Add (Tot,k+j+1,1,-map[i+1][j+1]), add (k+j+1,tot,0,map[i+1][j+1]);
} for (int i=1; i<=m; i++) Add (S,i,1,-map[1][i]), add (I,s,0,map[1][i]);
for (int i=1; i<=m+n-1; i++) Add (sum-m-n+i+1,t,inf,0), add (t,sum-m-n+i+1,0,0);
while (SPFA ());
printf ("%d\n",-ans); } inline void Work3 () {ans=tot=0; s=0; t=sum+1;
Clean ();
for (int i=1, i<n; i++) for (int j=1; j<=m+i-1; J + +) {tot++; int k= (2*m+i-1) * (I/2) + (i%2==0? 0:m+ (I/2));
Add (Tot,k+j,inf,-map[i+1][j]), add (K+j,tot,0,map[i+1][j]);
Add (Tot,k+j+1,inf,-map[i+1][j+1]), add (k+j+1,tot,0,map[i+1][j+1]);
} for (int i=1; i<=m; i++) Add (S,i,1,-map[1][i]), add (I,s,0,map[1][i]); for (int i=1; i<=m+n-1; i++) Add (sum-m-n+i+1,t,inf,0), add (t,sum-m-n+i+1,0,0);
while (SPFA ());
printf ("%d\n",-ans);
} int main () {freopen ("digit.in", "R", stdin);
Freopen ("Digit.out", "w", stdout);
M=in (), N=in ();
for (int i=1, i<=n; i++) for (int j=1; j<=m+i-1; j + +) Map[i][j]=in ();
sum= (2*m+n-1) * (N/2) + (n%2==0 0: (m+ (N/2))); s=0;
t= (sum<<1) +1;
Work1 ();//Rule one work2 ();//Rule two work3 ();//rule three return 0; }