P3376 网络流【模板】
网络:任意一张有向图,其中有N个点,M条边,源点S,汇点T
我们把c(x,y)称为容量,
把f(x,y)称为流量。
流函数的三大性质:
容量限制:每条边的流量总不可能大于该边的容量
f(x,y)<=c(x,y)
斜对称:正向边的流量=反向边的流量
f(x,y)=-f(y,x)
流量守恒:正向的所有流量和=反向的所有流量和
Any x!=S,x!=T,∑(u,x)∈E f(u,x)=∑(x,v)∈E f(x,v)
在任意时刻,网络中所有节点以及剩余容量大于0的边构成的子图被称为残量网络.
合法的流函数有很多,其中使得整个网络流量之和最大的流函数称为网络的最大流,此时的流量和被称为网络的最大流量
EK算法:
若一条从S到T的路径上所有边的剩余容量都大于0,则称这样的路径为一条增广路
EK算法的思想就是不断用BFS寻找增广路并不断更新最大流量值,直到网络上不存在增广路为止
我们不断寻找剩余流量大于零的边,寻找从S到T的路径,计算路径上各边剩余容量值的最小值dis,则网络的最大流量就可以增加dis,
(经过的正向边容量值全部减去dis,反向边全部加上dis)
反向边:给程序一个反悔的机会,防止直接更改值影响到之后寻找另外的增广路
我们添加正向边的同时添加反向边,更新边权的时候,我们就可以直接使用xor1的方式,找到对应的正向边和反向边(奇数异或1相当于-1,偶数异或1相当于+1)
代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=501000;
long long n,m,s,t;
struct node{
long long next,v,w;
}e[N];
long long tot=1,vis[N],pre[N],head[N],flag[2506][2506];
long long ans,dis[N];
long long bfs(){
for(int i=1;i<=n;i++) vis[i]=0;
queue <long long> q;
q.push(s);
vis[s]=1;
dis[s]=0x3f3f3f3f;
while(!q.empty()){
long long x=q.front();
q.pop();
for(int i=head[x];i;i=e[i].next){
if(!e[i].w) continue;
long long v=e[i].v;
if(vis[v]) continue;
dis[v]=min(dis[x],e[i].w);
pre[v]=i;
q.push(v);
vis[v]=1;
if(v==t) return 1;
}
}
return 0;
}
void update(){
long long x=t;
while(x!=s){
long long v=pre[x];
e[v].w-=dis[t];
e[v^1].w+=dis[t];
x=e[v^1].v;
}
ans+=dis[t];
}
void add(long long u,long long v,long long w){
e[++tot].v=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot;
e[++tot].v=u;
e[tot].w=0;
e[tot].next=head[v];
head[v]=tot;
}
int main(){
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
if(!flag[u][v]){
add(u,v,w);
flag[u][v]=tot;
}
else{
e[flag[u][v]-1].w+=w;
}
}
while(bfs()!=0){
update();
}
cout<<ans<<endl;
return 0;
}
Dinic
应用BFS生成分层图,然后用DFS实现多路增广。
代码:
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const long long INF=2019202408;
const int N=500010;
long long n,m,s,t;
long long tot=1,head[N];
struct node{
long long v,w,next;
}e[N<<2];
long long flag[2600][2600];
long long d[N];
long long vis[N],dis[N],now[N];
long long ans;
int bfs(){
for(int i=1;i<=n;i++) dis[i]=INF;
queue<long long> q;
q.push(s);
dis[s]=0;
now[s]=head[s];
while(q.size()){
long long x=q.front();
q.pop();
for(int i=head[x];i;i=e[i].next){
int v=e[i].v;
if(e[i].w>0&&dis[v]==INF){
q.push(v);
now[v]=head[v];
dis[v]=dis[x]+1;
if(v==t) return 1;
}
}
}
return 0;
}
int dfs(int x,long long sum){
if(x==t) return sum;
int k,res=0;
for(int i=now[x];i&∑i=e[i].next){
now[x]=i;
int v=e[i].v;
if(e[i].w>0&&(dis[v]==dis[x]+1)){
k=dfs(v,min(sum,e[i].w));
if(k==0) dis[v]=INF;
e[i].w-=k;
e[i^1].w+=k;
res+=k;
sum-=k;
}
}
return res;
}
void add(int u,int v,long long w){
e[++tot].v=v;
e[tot].w=w;
e[tot].next=head[u];
head[u]=tot;
e[++tot].v=u;
e[tot].w=0;
e[tot].next=head[v];
head[v]=tot;
return ;
}
int main(){
cin>>n>>m>>s>>t;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
if(!flag[u][v]){
add(u,v,w);
flag[u][v]=tot;
}
else{
e[flag[u][v]-1].w+=w;
}
}
while(bfs()){
ans+=dfs(s,INF);
}
cout<<ans;
return 0;
}

浙公网安备 33010602011771号