这篇博客主要记录的是几个有上下界网络流的模板,不会的就自己百度吧
找了几篇写得比较好的博客(思想的话我就不赘述了,看这些就行):博客1、博客2、博客3
【无源汇有上下界可行流】
有 n 个点, m 条边,每条边 e 有一个流量下界 l 和流量上界 r,求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。如果无解,输出一行 NO;否则第一行输出 YES,之后 m 行每行一个整数,表示每条边的流量。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 1000005
#define inf 1ll<<31ll-1
using namespace std;
int n,m,s,t,ss,tt,num=1;
int v[M],w[M],next[M];
int d[N],f[N],ll[N],sum[N],first[N];
void add(int x,int y,int f)
{
num++;
next[num]=first[x];
first[x]=num;
v[num]=y;
w[num]=f;
}
bool bfs(int start,int end)
{
int x,y,i,j;
memset(d,-1,sizeof(d));
memcpy(f,first,sizeof(f));
queue<int>q;
q.push(start);
d[start]=0;
while(!q.empty())
{
x=q.front();
q.pop();
for(i=first[x];i;i=next[i])
{
y=v[i];
if(w[i]&&d[y]==-1)
{
d[y]=d[x]+1;
if(y==end)
return true;
q.push(y);
}
}
}
return false;
}
int dinic(int now,int end,int flow)
{
if(now==end)
return flow;
int x,delta,ans=0;
for(int &i=f[now];i;i=next[i])
{
x=v[i];
if(w[i]&&d[x]==d[now]+1)
{
delta=dinic(x,end,min(flow,w[i]));
w[i]-=delta;
w[i^1]+=delta;
flow-=delta;
ans+=delta;
if(!flow) break;
}
}
if(flow) d[now]=-1;
return ans;
}
int main()
{
int x,y,i,j,l,r;
int ans=0,maxflow=0;
scanf("%d%d",&n,&m);
s=0,t=n+1;
ss=t+1,tt=ss+1;
for(i=1;i<=m;++i)
{
scanf("%d%d%d%d",&x,&y,&l,&r);
ll[num+1]=l;
sum[x]-=l,sum[y]+=l;
add(x,y,r-l),add(y,x,0);
}
for(i=1;i<=n;++i)
{
if(sum[i]>0) add(ss,i,sum[i]),add(i,ss,0),ans+=sum[i];
if(sum[i]<0) add(i,tt,-sum[i]),add(tt,i,0);
}
while(bfs(ss,tt))
maxflow+=dinic(ss,tt,inf);
if(maxflow!=ans)
{
printf("NO");
return 0;
}
printf("YES\n");
for(i=2;i<=2*m;i+=2)
printf("%d\n",w[i^1]+ll[i]);
return 0;
}
【有源汇有上下界最大流】
有 n 个点,m 条边,每条边 e 有一个流量下界 l 和流量上界 r,给定源点 s 与汇点 t ,求源点到汇点的最大流。如果无解,输出一行“please go home to sleep”;否则输出最大流。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 1000005
#define inf 1ll<<31ll-1
using namespace std;
int n,m,s,t,ss,tt,num=1;
int v[M],w[M],next[M];
int d[N],f[N],sum[N],first[N];
bool can[N];
void add(int x,int y,int f)
{
num++;
next[num]=first[x];
first[x]=num;
v[num]=y;
w[num]=f;
}
bool bfs(int start,int end)
{
int x,y,i,j;
memset(d,-1,sizeof(d));
memcpy(f,first,sizeof(f));
queue<int>q;
q.push(start);
d[start]=0;
while(!q.empty())
{
x=q.front();
q.pop();
for(i=first[x];i;i=next[i])
{
y=v[i];
if(w[i]&&d[y]==-1&&!can[y])
{
d[y]=d[x]+1;
if(y==end)
return true;
q.push(y);
}
}
}
return false;
}
int dinic(int now,int end,int flow)
{
if(now==end)
return flow;
int x,delta,ans=0;
for(int &i=f[now];i;i=next[i])
{
x=v[i];
if(w[i]&&d[x]==d[now]+1&&!can[x])
{
delta=dinic(x,end,min(flow,w[i]));
w[i]-=delta;
w[i^1]+=delta;
flow-=delta;
ans+=delta;
if(!flow) break;
}
}
if(flow) d[now]=-1;
return ans;
}
int main()
{
int x,y,i,j,l,r;
int ans=0,maxflow=0;
scanf("%d%d%d%d",&n,&m,&s,&t);
ss=0,tt=n+1;
for(i=1;i<=m;++i)
{
scanf("%d%d%d%d",&x,&y,&l,&r);
sum[x]-=l,sum[y]+=l;
add(x,y,r-l),add(y,x,0);
}
for(i=1;i<=n;++i)
{
if(sum[i]>0) add(ss,i,sum[i]),add(i,ss,0),ans+=sum[i];
if(sum[i]<0) add(i,tt,-sum[i]),add(tt,i,0);
}
add(t,s,inf),add(s,t,0);
while(bfs(ss,tt))
maxflow+=dinic(ss,tt,inf);
can[ss]=false;
can[tt]=false;
if(maxflow!=ans)
{
printf("please go home to sleep");
return 0;
}
maxflow=0;
while(bfs(s,t))
maxflow+=dinic(s,t,inf);
printf("%d",maxflow);
return 0;
}
【有源汇有上下界最小流】
有 n 个点,m 条边,每条边 e 有一个流量下界 l 和流量上界 r,给定源点 s 与汇点 t,求源点到汇点的最小流。如果无解,输出一行“please go home to sleep”;否则输出最小流。
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 1000005
#define inf 1ll<<31ll-1
using namespace std;
int n,m,s,t,ss,tt,num=1;
int v[M],w[M],next[M];
int d[N],f[N],sum[N],first[N];
bool can[N];
void add(int x,int y,int f)
{
num++;
next[num]=first[x];
first[x]=num;
v[num]=y;
w[num]=f;
}
bool bfs(int start,int end)
{
int x,y,i,j;
memset(d,-1,sizeof(d));
memcpy(f,first,sizeof(f));
queue<int>q;
q.push(start);
d[start]=0;
while(!q.empty())
{
x=q.front();
q.pop();
for(i=first[x];i;i=next[i])
{
y=v[i];
if(w[i]&&d[y]==-1&&!can[y])
{
d[y]=d[x]+1;
if(y==end)
return true;
q.push(y);
}
}
}
return false;
}
int dinic(int now,int end,int flow)
{
if(now==end)
return flow;
int x,delta,ans=0;
for(int &i=f[now];i;i=next[i])
{
x=v[i];
if(w[i]&&d[x]==d[now]+1&&!can[x])
{
delta=dinic(x,end,min(flow,w[i]));
w[i]-=delta;
w[i^1]+=delta;
flow-=delta;
ans+=delta;
if(!flow) break;
}
}
if(flow) d[now]=-1;
return ans;
}
int main()
{
int x,y,i,j,l,r;
int ans=0,maxflow=0;
scanf("%d%d%d%d",&n,&m,&s,&t);
ss=0,tt=n+1;
for(i=1;i<=m;++i)
{
scanf("%d%d%d%d",&x,&y,&l,&r);
sum[x]-=l,sum[y]+=l;
add(x,y,r-l),add(y,x,0);
}
for(i=1;i<=n;++i)
{
if(sum[i]>0) add(ss,i,sum[i]),add(i,ss,0),ans+=sum[i];
if(sum[i]<0) add(i,tt,-sum[i]),add(tt,i,0);
}
add(t,s,inf),add(s,t,0);
while(bfs(ss,tt))
maxflow+=dinic(ss,tt,inf);
can[ss]=false;
can[tt]=false;
if(maxflow!=ans)
{
printf("please go home to sleep");
return 0;
}
int minflow=0;
add(t,s,-inf),add(s,t,0);
while(bfs(t,s))
minflow-=dinic(t,s,inf);
printf("%d",minflow);
return 0;
}