[网络流24题][CODEVS1237]餐巾计划问题(费用流)
2016-03-09 16:23
591 查看
题目描述
传送门题解
拆点,把每天的点拆成xi和yi,xi表示每一天的脏毛巾,yi表示每一天的新毛巾。从超级源向xi连边,容量为ri,费用为0;
从yi向超级汇连边,容量为ri,费用为0;
从超级源向yi连边,容量为INF,费用为p;
从xi分别向y(i+m)连边(i+m<=N),容量为INF,费用为f;
从xi分别向y(i+n)连边(i+n<=N),容量为INF,费用为m;
从xi向x(i+1)连边,容量为INF,费用为0;
以上建图分别表示:每天产生的脏毛巾;每天需要准备的新毛巾;每天新买进的毛巾;快洗毛巾;慢洗毛巾;延期送洗。
用最小费用最大流求解即可。
这道题的处理方法及其巧妙,注重理解。
代码
#include<iostream> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int max_N=1005; const int max_Max=max_N*2+2; const int max_m=max_Max*20; const int max_e=max_m*2; const int inf=1e9; int N,p,m,f,n,s,Max,maxflow,mincost,r[max_N]; int point[max_Max],next[max_e],v[max_e],remain[max_e],c[max_e],tot; int last[max_Max],dis[max_Max]; bool vis[max_Max]; queue <int> q; inline void addedge(int x,int y,int cap,int z){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap; c[tot]=z; ++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; c[tot]=-z; } inline int addflow(int s,int t){ int ans=inf,now=t; while (now!=s){ ans=min(ans,remain[last[now]]); now=v[last[now]^1]; } now=t; while (now!=s){ remain[last[now]]-=ans; remain[last[now]^1]+=ans; now=v[last[now]^1]; } return ans; } inline bool bfs(int s,int t){ memset(dis,0x7f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[s]=0; vis[s]=true; while (!q.empty()) q.pop(); q.push(s); while (!q.empty()){ int now=q.front(); q.pop(); vis[now]=false; for (int i=point[now];i!=-1;i=next[i]) if (dis[v[i]]>dis[now]+c[i]&&remain[i]){ dis[v[i]]=dis[now]+c[i]; last[v[i]]=i; if (!vis[v[i]]){ vis[v[i]]=true; q.push(v[i]); } } } if (dis[t]>inf) return false; int flow=addflow(s,t); maxflow+=flow; mincost+=flow*dis[t]; return true; } inline void major(int s,int t){ maxflow=0; mincost=0; while (bfs(s,t)); } int main(){ tot=-1; memset(point,-1,sizeof(point)); memset(next,-1,sizeof(next)); scanf("%d%d%d%d%d%d",&N,&p,&m,&f,&n,&s); for (int i=1;i<=N;++i) scanf("%d",&r[i]); Max=N*2+2; //从超级源向每天的脏毛巾连边,费用0,容量ri for (int i=1;i<=N;++i) addedge(1,1+i,r[i],0); //从每天的新毛巾向超级汇连边,费用0,容量ri for (int i=1;i<=N;++i) addedge(1+N+i,Max,r[i],0); //从超级源向每天的新毛巾连边,费用p,容量INF for (int i=1;i<=N;++i) addedge(1,1+N+i,inf,p); //从每天的脏毛巾向下一天的脏毛巾连边(延期送洗),费用0,容量INF for (int i=1;i<N;++i) addedge(1+i,1+i+1,inf,0); //从每天的脏毛巾向快洗或慢洗完成后的一天的新毛巾连边,费用为快洗或慢洗的费用,容量INF for (int i=1;i<=N;++i){ if (i+m<=N) addedge(1+i,1+N+i+m,inf,f); if (i+n<=N) addedge(1+i,1+N+i+n,inf,s); } major(1,Max); printf("%d\n",mincost); }
总结
①最小费用最大流是在保证最大流的基础上实现最小费用。那么我们就可以把最大流看成一个控制条件。意思就是满足题意的解必须建立在跑满最大流的基础之上。②没有严格限制的边容量都可以设为INF,刚开始看起来貌似不科学,实际上有了该控制的条件的控制,这些边都可以看成是一种保证流量的关系,费用的话视情况而定。
相关文章推荐
- TCP和UDP的区别
- 通信协议 HTTP TCP UDP
- 游戏服务器:到底使用UDP还是TCP
- 关于TCP/IOCP构架中出现的假死连接解决方案
- 七层协议与网络配置
- lighttpd(mac系统下)里面使用cgi脚本(包括lighttpd的安装)
- swift:使用NSJSONSerialization和SwiftyJSON两种方法解析网络返回的json格式数据
- 理解TCP/IP三次握手与四次挥手的正确姿势
- servlet客户端http请求及响应及httpservletrequest,httpservletresponse详解
- android从网络获取图片直接存为bitmap
- Tcp
- 协议(protocol)与网络协议
- iOS开发网络篇—HTTP协议
- TCP (下)
- TCP (上)
- Postman -- HTTP请求的Chrome插件
- 深入理解HTTP协议
- tcp粘包分析
- 移动应用-使用tcpdump抓包
- HTTP POST请求报文格式分析与Java实现文件上传