您的位置:首页 > 理论基础 > 计算机网络

【网络流24题】No.16 数字梯形问题 (不相交路径 最大费用流)

2016-11-06 20:37 627 查看
【题意】

  给定一个由 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 }


View Code



2016-11-06 20:41:45
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐