V#include
using namespace std;
bool vis[200001];int dist[200001];//vis是spfa访问标记及増广访问标记,dist是每个点距离标号
int n,m,s,t,ans=0;//s是起点,t是终点,ans是费用答案
int nedge=-1,p[200001],c[200001],cc[200001],nex[200001],head[200001];//nedge为边编号
//p,c,cc,nex表编号为i的边终点,流量,费用,下一条边,head表编号为i的点射出的最后一边
void addedge(int x,int y,int z,int zz){
p[++nedge]=y;c[nedge]=z;cc[nedge]=zz;nex[nedge]=head[x];head[x]=nedge;
} //建边(数组模拟边表倒挂)
bool spfa(int s,int t){
memset(vis,0,sizeof vis); //深搜前先清0
for(int i=0;i<=n;i++)dist[i]=1e9;
dist[t]=0;vis[t]=1; //SPFA维护距离标号要倒着跑,维护出到终点的最短路径
dequeq;q.push_back(t); //使用了SPFA的队列优化
while(!q.empty()){
int now=q.front();q.pop_front();
for(int k=head[now];k>-1;k=nex[k]){ //下一行的k^1可保证正流
if(c[k^1]&&dist[p[k]]>dist[now]-cc[k]){ //SPFA倒着跑故c[k]对应反向边是为正
dist[p[k]]=dist[now]-cc[k];//已经倒着,建边时反向边权为负,故负负得正
if(!vis[p[k]]){
vis[p[k]]=1;
if(!q.empty()&&dist[p[k]]-1;k=nex[k])
if(!vis[p[k]]&&c[k]&&dist[x]-cc[k]==dist[p[k]]){//未访问,有流量,此边在最短路径上
a=dfs(p[k],min(c[k],low-used)); //往下一个点深搜且流量降低
if(a)ans+=a*cc[k],c[k]-=a,c[k^1]+=a,used+=a;//深搜有流:加钱,减流,加流,递归流
if(used==low)break; //流量流完了可以退出(本题可忽略)
} //这题最大流不定,故开了1E9无限大
return used;
}
int costflow(){ //开始跑
int flow=0; //开始时流量为0
while(spfa(s,t)){ //判断起点终点是否连通,不连通则满流退出
vis[t]=1; //只是为了第一次可以进入vis
while(vis[t]){
memset(vis,0,sizeof vis); //先清零,看下面的深搜能否更新到终点
flow+=dfs(s,1e9); //一直増广直到走不到为止
}
}
return flow; //返回最大流,费用在ans里
}
int main(){
memset(nex,-1,sizeof nex);memset(head,-1,sizeof head);//初始化nex与head数组
scanf("%d%d%d%d",&n,&m,&s,&t); //输入点数,边数,起点,终点
for(int i=1;i<=m;i++){ //逐条边输入
int x,y,z,zz;scanf("%d%d%d%d",&x,&y,&z,&zz); //起点,终点,可流量,花费
addedge(x,y,z,zz);addedge(y,x,0,-zz);
}
printf("%d ",costflow());printf("%d",ans); //输入最大流时流量与费用
return 0;
}
Zkw费用流
洛谷3381最小费用最大流
题目描述
如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
输入第一行四个正整数N、M、S、T,表示点的个数、有向边的个数、源点序号、汇点序号。接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。
输出最大流量和在最大流量情况下的最小费用。
输入: 输出:
4 5 4 3 50 280
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5
zkw费用流的优缺点:
原版优势:节省了大量的跑SPFA的时间,还有多路増广的大优势,这个特点可以在许多路径都费用相同的时候派上用场, 进一步减少了重标号的时间耗费
zkw优势:SPFA多路増广版本多跑了SPFA,多路増广的优势犹存,所以时间上还是蛮优秀的,再加上SLF优化之后减小的常数也是很高效的
zkw劣势:对于流量不大, 费用不小, 增广路还较长的网络,zkw体现出来的优势并不大,甚至可能比普通EK慢