【题目大意】

给定一张有向图,每条边都有一个容量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=+;
const int MAXM=+;
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,,E[u].size()-,-w});/*失误把这里敲成了E[u],看了好久才看出来T T*/
} void init()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=;i<m;i++)
{
scanf("%d%d%d%d",&U[i],&V[i],&C[i],&W[i]);
addedge(U[i],V[i],C[i],);
}
} int bfs()
{
queue<int> que;
memset(dis,-,sizeof(dis));
dis[]=;
que.push();
while (!que.empty())
{
int head=que.front();que.pop();
for (int i=;i<E[head].size();i++)
{
node tmp=E[head][i];
if (dis[tmp.to]==- && tmp.cap>)
{
dis[tmp.to]=dis[head]+;
que.push(tmp.to);
}
}
}
if (dis[n]==-) return ;
else return ;
} int dfs(int s,int e,int f)
{
vis[s]=;
if (s==e) return f;
for (int i=;i<E[s].size();i++)
{
node& tmp=E[s][i];
if (!vis[tmp.to] && tmp.cap> && dis[tmp.to]==dis[s]+)
{
int delta=dfs(tmp.to,e,min(f,tmp.cap));
if (delta>)
{
tmp.cap-=delta;
E[tmp.to][tmp.pos].cap+=delta;
return delta;
}
}
}
return ;
} void dinic()
{
int flow=;
while (bfs())
{
memset(vis,,sizeof(vis));
int f=dfs(,n,INF);
if (f==) break;
else flow+=f;
}
cout<<flow<<' ';
} void rebuild()
{
for (int i=;i<m;i++) addedge(U[i],V[i],INF,W[i]);
addedge(,,k,);
} int spfa(int u,int v)
{
memset(vis,,sizeof(vis));
for (int i=;i<=n;i++) dis[i]=INF;
memset(pre,-,sizeof(pre));
queue<int> que;
dis[]=;
vis[]=;
que.push();
while (!que.empty())
{
int head=que.front();
que.pop();
vis[head]=;
for (int i=;i<E[head].size();i++)
{
node& tmp=E[head][i];
if (tmp.cap> && 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]=;
que.push(tmp.to);
}
}
}
}
if (dis[n]==INF) return ;
else return ;
} void mcf()
{
int ans=;
while (spfa(,n))
{
int flow=INF;
for (int i=n;pre[i]!=-;i=pre[i])
flow=min(flow,E[pre[i]][preedge[i]].cap);
for (int i=n;pre[i]!=-;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 ;
}

【最大流/费用流】BZOJ1834-[ZJOI2010]network 网络扩容的更多相关文章

  1. BZOJ1834 [ZJOI2010]network 网络扩容 【最大流,费用流】

    1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec  Memory Limit: 64 MB Submit: 3394  Solved: 1774 [Subm ...

  2. [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流

    1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec  Memory Limit: 64 MB Submit: 3330  Solved: 1739 [Subm ...

  3. 【最大流】【费用流】bzoj1834 [ZJOI2010]network 网络扩容

    引用题解: 最大流+费用流. 第一问最大流即可. 第二问为“最小费用最大流”. 由题意,这一问的可转化为在上一问的“残量网络”上,扩大一些边的容量,使能从新的图中的最大流为k. 那么易得:对于还有剩余 ...

  4. bzoj1834: [ZJOI2010]network 网络扩容 费用流

    bzoj1834 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的情况下,1到N的最大流: 2.将1到N的最大流增加K所需的最小扩容 ...

  5. 2018.10.13 bzoj1834: [ZJOI2010]network 网络扩容(最大流+费用流)

    传送门 网络流水题啊. 第一问直接放心跑最大流(本来还以为有什么tricktricktrick). 第二问就直接把原来的边(u,v,c,w)(u,v,c,w)(u,v,c,w)变成(u,v,c,0)( ...

  6. 【费用流】bzoj1834: [ZJOI2010]network 网络扩容

    还是稍微记一下这个拆点模型吧 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求:  1.在不扩容的情况下,1到N的最大流:  ...

  7. bzoj1834 [ZJOI2010]network 网络扩容

    第一问跑最大流,第二问新建一条边连接0和1,流量为上第一问的答案+k,费用为0,接下来图中每条边拆成两条边,第一条容量为C费用为0,第二条容量无穷费用为W,再跑一遍费用流即可. 代码 #include ...

  8. BZOJ1834 [ZJOI2010]network 网络扩容(最小费用最大流)

    挺直白的构图..最小费用最大流的定义. #include<cstdio> #include<cstring> #include<queue> #include< ...

  9. 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流

    [BZOJ1834][ZJOI2010]network 网络扩容 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不 ...

  10. BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)

    第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然  后跑最小费用最大流就OK了. ---- ...

随机推荐

  1. Python模块学习 - IPy

    简介 在IP地址规划中,涉及到计算大量的IP地址,包括网段.网络掩码.广播地址.子网数.IP类型等,即便是专业的网络人员也要进行繁琐的计算,而IPy模块提供了专门针对IPV4地址与IPV6地址的类与工 ...

  2. linux平台学x86汇编语言学习集合帖

    linux平台学x86汇编语言学习集合帖 linux平台学x86汇编(一):https://blog.csdn.net/shallnet/article/details/45543237 linux平 ...

  3. TCP之Nagle算法&&延迟ACK

    1. Nagle算法: 是为了减少广域网的小分组数目,从而减小网络拥塞的出现: 该算法要求一个tcp连接上最多只能有一个未被确认的未完成的小分组,在该分组ack到达之前不能发送其他的小分组,tcp需要 ...

  4. Qualcomm platform, the commonly used parameters of charger and battery in device tree file

    Platform MSM8917 PM8937 PMI8940 Parameters 1 battery charging voltage : qcom,float-voltage-mv = < ...

  5. python基础===zmail,收发邮件的模块

    项目地址: GitHub:https://github.com/ZYunH/zmail  介绍: https://mp.weixin.qq.com/s?__biz=MzAxMjUyNDQ5OA==&a ...

  6. jmeter===JMeter 中Random 随机函数的使用(转)

    原文:http://blog.csdn.net/dreamtl/article/details/68952272 场景:在做接口测试时,比如说要求用户的手机号码不允许重复,那此时可以通过Random ...

  7. linux子系统的初始化_subsys_initcall()【转】

    转自:http://my.oschina.net/u/572632/blog/305492 目录[-] 概述 section的声明 注册 调用 IN BUILDING 概述 内核选项的解析完成之后,各 ...

  8. linux和ubuntu防火墙相关命令

    1.永久有效 开启: chkconfig iptables on 关闭: chkconfig iptables off 2.即刻生效 开启: service iptables start 关闭: se ...

  9. 【COGS2622】后缀平衡树

    这是个后缀平衡树的裸题.... 然后傻逼的我调了一下午. #include<bits/stdc++.h> typedef long long ll; using namespace std ...

  10. 设计模式之笔记--原型模式(Prototype)

    原型模式(Prototype) 定义 原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 类图 描述 提供一个克隆自身的接口--Clone方法. 应用场景 ...