COGS738 [网络流24题] 数字梯形(最小费用最大流)
2016-04-11 16:40
447 查看
题目这么说:
给定一个由n 行数字组成的数字梯形如下图所示。梯形的第一行有m 个数字。从梯形
的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶
至底的路径。
规则1:从梯形的顶至底的m条路径互不相交。
规则2:从梯形的顶至底的m条路径仅在数字结点处相交。
规则3:从梯形的顶至底的m条路径允许在数字结点相交或边相交。
对于给定的数字梯形,分别按照规则1,规则2,和规则3 计算出从梯形的顶至底的m
条路径,使这m条路径经过的数字总和最大。
对那三种情况分别建容量网络跑最小费用最大流,这个很容易的。。要注意题意上说的是顶部m个数字分别作为m条路径的出发点。
给定一个由n 行数字组成的数字梯形如下图所示。梯形的第一行有m 个数字。从梯形
的顶部的m 个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶
至底的路径。
规则1:从梯形的顶至底的m条路径互不相交。
规则2:从梯形的顶至底的m条路径仅在数字结点处相交。
规则3:从梯形的顶至底的m条路径允许在数字结点相交或边相交。
对于给定的数字梯形,分别按照规则1,规则2,和规则3 计算出从梯形的顶至底的m
条路径,使这m条路径经过的数字总和最大。
对那三种情况分别建容量网络跑最小费用最大流,这个很容易的。。要注意题意上说的是顶部m个数字分别作为m条路径的出发点。
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; #define INF (1<<30) #define MAXN 888 #define MAXM 888*888*2 struct Edge{ int u,v,cap,cost,next; }edge[MAXM]; int head[MAXN]; int NV,NE,vs,vt; void addEdge(int u,int v,int cap,int cost){ edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost; edge[NE].next=head[u]; head[u]=NE++; edge[NE].u=v; edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost; edge[NE].next=head[v]; head[v]=NE++; } bool vis[MAXN]; int d[MAXN],pre[MAXN]; bool SPFA(){ for(int i=0;i<NV;++i){ vis[i]=0; d[i]=INF; } vis[vs]=1; d[vs]=0; queue<int> que; que.push(vs); while(!que.empty()){ int u=que.front(); que.pop(); for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(edge[i].cap && d[v]>d[u]+edge[i].cost){ d[v]=d[u]+edge[i].cost; pre[v]=i; if(!vis[v]){ vis[v]=1; que.push(v); } } } vis[u]=0; } return d[vt]!=INF; } int MCMF(){ int res=0; while(SPFA()){ int flow=INF,cost=0; for(int u=vt; u!=vs; u=edge[pre[u]].u){ flow=min(flow,edge[pre[u]].cap); } for(int u=vt; u!=vs; u=edge[pre[u]].u){ edge[pre[u]].cap-=flow; edge[pre[u]^1].cap+=flow; cost+=flow*edge[pre[u]].cost; } res+=cost; } return res; } int a[22][44],idx[22][44]; int main(){ freopen("digit.in","r",stdin); freopen("digit.out","w",stdout); int m,n; scanf("%d%d",&m,&n); int cnt=0; for(int i=0; i<n; ++i){ for(int j=0; j<m+i; ++j) scanf("%d",&a[i][j]),idx[i][j]=cnt++; } vs=cnt*2; vt=vs+1; NV=vt+1; NE=0; memset(head,-1,sizeof(head)); for(int i=0; i<n; ++i){ for(int j=0; j<m+i; ++j){ addEdge(idx[i][j],idx[i][j]+cnt,1,-a[i][j]); if(i==0) addEdge(vs,idx[i][j],1,0); if(i==n-1) addEdge(idx[i][j]+cnt,vt,1,0); else{ addEdge(idx[i][j]+cnt,idx[i+1][j],1,0); addEdge(idx[i][j]+cnt,idx[i+1][j+1],1,0); } } } printf("%d\n",-MCMF()); vs=cnt*2; vt=vs+1; NV=vt+1; NE=0; memset(head,-1,sizeof(head)); for(int i=0; i<n; ++i){ for(int j=0; j<m+i; ++j){ addEdge(idx[i][j],idx[i][j]+cnt,INF,-a[i][j]); if(i==0) addEdge(vs,idx[i][j],1,0); if(i==n-1) addEdge(idx[i][j]+cnt,vt,INF,0); else{ addEdge(idx[i][j]+cnt,idx[i+1][j],1,0); addEdge(idx[i][j]+cnt,idx[i+1][j+1],1,0); } } } printf("%d\n",-MCMF()); vs=cnt*2; vt=vs+1; NV=vt+1; NE=0; memset(head,-1,sizeof(head)); for(int i=0; i<n; ++i){ for(int j=0; j<m+i; ++j){ addEdge(idx[i][j],idx[i][j]+cnt,INF,-a[i][j]); if(i==0) addEdge(vs,idx[i][j],1,0); if(i==n-1) addEdge(idx[i][j]+cnt,vt,INF,0); else{ addEdge(idx[i][j]+cnt,idx[i+1][j],INF,0); addEdge(idx[i][j]+cnt,idx[i+1][j+1],INF,0); } } } printf("%d",-MCMF()); return 0; }
相关文章推荐
- hdu5294-网络流+最短路
- apache httpd-2.4.18 安装教程
- iOS应用架构谈 网络层设计方案
- unix网络编程笔记(四)--IO复用
- hdu4975 -网络流
- 卷积神经网络反向推导算法
- 关于TCP的一些零散知识
- 浏览器 HTTP 协议缓存机制详解
- 安卓使用http下载文件
- ZStack禁止入网
- android中判断网络连接是否可用
- HttpPost实现Request Payload
- 用webmagic实现的网络爬虫
- zz: virsual studio等AP无法访问网络映射驱动器(netmap drive)的解决办法
- HTTP基础与Android之——使用HttpClient和HttpURLConnection
- HTTP 500.22 错误解决
- iOS学习笔记13-网络(二)NSURLSession
- iOS学习笔记14-网络(三)WebView
- iOS学习笔记12-网络(一)NSURLConnection
- 获取网络日期时间,并设置本机系统日期时间