【网络流】CF708D Incorrect Flow

思考过程。无脑记录。

流量守恒:记 d(x)=inxoutx,d(x)=0,因为上下界网络流经常这么表示,当然记 d(x)=outxinx 也行。

减容量是可以舍弃的操作,因为减容量总是可以使用减流量解决或者会使其更不优。

再者,每条边给定的原始流量一定要先流满再说,所以上下界都是 f

下面都省略了下界 0。

fc,那么在不增加 c 的情况下,f 还能加 cf,考虑对 d(u),d(v) 的影响,假如加了 l,那么 d(u)=l,d(v)+=l。考虑这个式子如何建模吧。若原来的 d(x)>0,x[1,n] 说明入流多,要流出。对应的,对 d(x)<0 的,要流入,这部分有助于建模思考。考虑加 1,那么就是 (u,v,cf,1),即假如需要流经这条边,则会给 u 提供流出流量,给 v 提供流入流量。考虑减 1,那么就是对称的 (v,u,f,1)。再考虑下当 f=c 的时候,这时候我们要增加流量的话,只能加容量再加流量,即花费 2。那么就是 (u,v,+,2)

f>c,欸,我不会,睡觉了。

考虑增加流量,那么先要增加 fc 的容量(这东西我还没想明白咋建模,主要是这个花费应该只能后面跑完在算吧),且后面每次增加流量都要增加容量,即 (u,v,+,2)。减少流量,那么先要减少 fc 的流量,再 (v,u,c,1)。好像漏了些,不懂。。。

总算明白了,cff 也算一种情况,那么 (ff)+(fc)=fc,花费始终是 fc 的,所以无论如何 f>c 的情况都有一个固定原始花费。那么这样子算减少流量,即 (v,u,fc,0),即最多可以减少这么多,因为只要保证 cff 即可。

#include <bits/stdc++.h> #define int long long #define inf (int)(2e15) using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } #define N (int)(2e5+5) struct edge { int nex,to,w,c; }e[N<<1]; int chea[N],hea[N],d[N],cnt=1,n,m,ans,S,T,s,t; void add_edge(int x,int y,int z,int c) { e[++cnt].nex=hea[x]; e[cnt].to=y; e[cnt].w=z; e[cnt].c=c; hea[x]=cnt; } void add(int x,int y,int z,int c) { add_edge(x,y,z,c); add_edge(y,x,0,-c); } void lradd(int x,int y,int l,int r,int c) { add(x,y,r-l,c); d[x]-=l; d[y]+=l; } namespace WLL { queue<int>q; int dis[N],S,T; bool vis[N]; bool spfa() { for(int i=0;i<=T;i++) dis[i]=inf,vis[i]=0; dis[S]=0; q.push(S); while(!q.empty()) { int x=q.front(); q.pop(); vis[x]=0; for(int i=hea[x];i;i=e[i].nex) { int y=e[i].to; if(e[i].w&&dis[y]>dis[x]+e[i].c) { dis[y]=dis[x]+e[i].c; if(!vis[y]) vis[y]=1,q.push(y); } } } return dis[T]<inf; } int dfs(int x,int lim) { if(x==T||!lim) return lim; int flow=0,fl; vis[x]=1; for(int i=hea[x];i&&lim;i=e[i].nex) { int y=e[i].to; if(e[i].w&&!vis[y]&&dis[y]==dis[x]+e[i].c) { fl=dfs(y,min(lim,e[i].w)); if(!fl) continue; flow+=fl; lim-=fl; e[i].w-=fl; e[i^1].w+=fl; ans+=e[i].c*fl; } } if(!flow) dis[x]=inf; vis[x]=0; return flow; } void zkw(int ss,int tt) { S=ss; T=tt; while(spfa()) { memset(vis,0,sizeof(int)*(T+2)); dfs(S,inf); } } } signed main() { n=rd(); m=rd(); s=1; t=n; S=0; T=n+1; for(int i=1;i<=m;i++) { int x=rd(),y=rd(),c=rd(),f=rd(); lradd(x,y,f,f,0); if(f<=c) { lradd(x,y,0,c-f,1); lradd(y,x,0,f,1); lradd(x,y,0,inf,2); } else { ans+=f-c; lradd(x,y,0,inf,2); lradd(y,x,0,c,1); lradd(y,x,0,f-c,0); } } lradd(t,s,0,inf,0); for(int i=1;i<=n;i++) { if(d[i]>0) add(S,i,d[i],0); else if(d[i]<0) add(i,T,-d[i],0); } WLL::zkw(S,T); printf("%lld",ans); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15872282.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示