【网络流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\n",t[i].x,t[i].y,t[i].f,t[i].c); 67 printf("\n"); 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\n",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\n",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\n",ans); 152 return 0; 153 }
2016-11-06 20:41:45