【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容
2016-03-01 15:51
489 查看
【题目大意】
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
【思路】
问题用Dinic搞一搞。问题二可以看出是费用流。
(1)残余网络中边还有一些容量,而如果利用这些容量,是不需要花费新的费用的。则将这些边的费用设置为0。
(2)对于原有的边,添加一条起点、终点相同的点,容量设置为INF,费用设置为一开始输入的扩容费用。再添加一个超级源点,和1之间添加一条边,容量为K,费用为0。
所谓的费用流,就是将EK中每一次搜索改为关于单位费用的SPFA即可,其余板块类似。
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。
【思路】
问题用Dinic搞一搞。问题二可以看出是费用流。
(1)残余网络中边还有一些容量,而如果利用这些容量,是不需要花费新的费用的。则将这些边的费用设置为0。
(2)对于原有的边,添加一条起点、终点相同的点,容量设置为INF,费用设置为一开始输入的扩容费用。再添加一个超级源点,和1之间添加一条边,容量为K,费用为0。
所谓的费用流,就是将EK中每一次搜索改为关于单位费用的SPFA即可,其余板块类似。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> using namespace std; const int MAXN=1000+50; const int MAXM=5000+50; const int INF=0x7fffffff; int n,m,k;//点数边数和需要扩充的容量 struct node { int to,cap,pos,w; }; vector<node> E[MAXN]; int vis[MAXN]; int dis[MAXN]; int U[MAXM],V[MAXM],C[MAXM],W[MAXM]; int pre[MAXN],preedge[MAXN];//记录每次SPFA中每一个节点的前驱,以及当前节点在前驱的vector中是第几条边 void addedge(int u,int v,int c,int w) { E[u].push_back((node){v,c,E[v].size(),w}); E[v].push_back((node){u,0,E[u].size()-1,-w});/*失误把这里敲成了E[u],看了好久才看出来T T*/ } void init() { scanf("%d%d%d",&n,&m,&k); for (int i=0;i<m;i++) { scanf("%d%d%d%d",&U[i],&V[i],&C[i],&W[i]); addedge(U[i],V[i],C[i],0); } } int bfs() { queue<int> que; memset(dis,-1,sizeof(dis)); dis[1]=0; que.push(1); while (!que.empty()) { int head=que.front();que.pop(); for (int i=0;i<E[head].size();i++) { node tmp=E[head][i]; if (dis[tmp.to]==-1 && tmp.cap>0) { dis[tmp.to]=dis[head]+1; que.push(tmp.to); } } } if (dis ==-1) return 0; else return 1; } int dfs(int s,int e,int f) { vis[s]=1; if (s==e) return f; for (int i=0;i<E[s].size();i++) { node& tmp=E[s][i]; if (!vis[tmp.to] && tmp.cap>0 && dis[tmp.to]==dis[s]+1) { int delta=dfs(tmp.to,e,min(f,tmp.cap)); if (delta>0) { tmp.cap-=delta; E[tmp.to][tmp.pos].cap+=delta; return delta; } } } return 0; } void dinic() { int flow=0; while (bfs()) { memset(vis,0,sizeof(vis)); int f=dfs(1,n,INF); if (f==0) break; else flow+=f; } cout<<flow<<' '; } void rebuild() { for (int i=0;i<m;i++) addedge(U[i],V[i],INF,W[i]); addedge(0,1,k,0); } int spfa(int u,int v) { memset(vis,0,sizeof(vis)); for (int i=0;i<=n;i++) dis[i]=INF; memset(pre,-1,sizeof(pre)); queue<int> que; dis[0]=0; vis[0]=1; que.push(0); while (!que.empty()) { int head=que.front(); que.pop(); vis[head]=0; for (int i=0;i<E[head].size();i++) { node& tmp=E[head][i]; if (tmp.cap>0 && dis[tmp.to]>dis[head]+tmp.w) { dis[tmp.to]=dis[head]+tmp.w; pre[tmp.to]=head; preedge[tmp.to]=i; if (!vis[tmp.to]) { vis[tmp.to]=1; que.push(tmp.to); } } } } if (dis ==INF) return 0; else return 1; } void mcf() { int ans=0; while (spfa(1,n)) { int flow=INF; for (int i=n;pre[i]!=-1;i=pre[i]) flow=min(flow,E[pre[i]][preedge[i]].cap); for (int i=n;pre[i]!=-1;i=pre[i]) { node& tmp=E[pre[i]][preedge[i]]; tmp.cap-=flow; E[tmp.to][tmp.pos].cap+=flow; ans+=flow*tmp.w; } } cout<<ans<<endl; } int main() { init(); dinic(); rebuild(); mcf(); return 0; }
相关文章推荐
- [java] 6、获取本地机器网络地址信息
- 国外标杆性的网络综合布线(完美的艺术品)
- java网络编程+通讯协议
- maven3实战之设置HTTP代理
- Android带Cookie的Http请求
- 解决apache启动错误"httpd:Could not reliably determine...
- JavaWeb中的HttpSession对象
- Unix Study之--AIX 6.1配置网络安装服务
- POJ 1149 PIGS 网络流——【论建图的重要性QAQ】
- BP神经网络求解异或问题(Python实现)
- Unix Study之--AIX 6.1配置网络安装服务
- http协议学习系列
- 细说 ASP.NET控制HTTP缓存
- 移动通信网络
- httpClient对post内容gzip压缩和server端解压接收
- TCP程序设计
- 网络基本原理和加密
- angularJS $http 服务
- Http请求备忘httppost
- HTTP协议的安全性--全站HTTPS