什么是网络流呢?
网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关 --百度百科
在网络流这,概念非常的杂乱,理解清楚网络流中的概念是以后做题的关键,所以本篇blog主要讲概念。
1.流网络
如图,1为源点,6为汇点。
流网络的每条边都有一个属性,叫做每条边的容量。我们可以把问题想成输水管输水,两个节点之间代表一条水管,每条水管都有各自的最大输水量。
比如:
源点有无穷多的流量可以向外流,汇点可以源源不断的接收。这就是流网络(此时不考虑反向边)。
2.可行流
当流量满足两个限制才是可行流,这两个限制分别为容量限制和流量守恒.
容量限制很好理解,那么流量守恒是什么呢?
这一张图里,除了源点和汇点之外是不存储流量的,也就是除了源点和汇点的每个点流进去多少流量,也就流出来多少,这就是流量守恒。
3.最大流
最大流就是指所有可行流里流量最大的那个,也可称最大可行流。
红色代表实际流量,很明显看出所有可行流符合限制,所以这张图的最大流就为7。
4.残留网络
残留网络是根据各个可行流来说的,可行流不同,残留网络也不同。
这是根据上面的例子所造的图,我们可以看出现在流网络的可行流和残留网络的可行流相加就是是原图的可行流。
再附上求最大流的EK算法,余下的以后填坑.
点击查看代码
#include<bits/stdc++.h>
#define I using
#define her std
#define very_much ;
#define ll long long
#define Love namespace
#define INF 0x7fffffff
I Love her very_much
int n,m,s,to;
int head_size=1;
namespace lovespace
{
//---------------------------------
#define lim 0.004;
#define d 0.996
double calc();
void sa();
void work_sa()
{
for(int i=1;i<=1e9&&(double)clock()/CLOCKS_PER_SEC<=0.95;i++);
}
#undef d
//----------------------------------
#define maxn 50000
int fa[maxn],head[maxn],inque[maxn];
struct edge{
int f,t,nxt,val;
}e[maxn];
struct Pre{
int bak,nxt;
}pre[maxn];
#undef maxn
//-----------------------------------
void swp(int &x,int &y)
{
if(x==y) return;
x^=y^=x^=y;
}
//-----------------------------------
int fmod(int a,int b,int p)
{
int sum=1;
while(b>0)
{
if(b&1) sum=sum*a%p;
a=a*a%p;
b=b>>1;
}
int ans=sum%p;
return ans;
}
//-----------------------------------
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
//----------------------------------
bool bfs()
{
queue<int>q;
memset(inque,0,sizeof(inque));
memset(pre,-1,sizeof(pre));
inque[s]=1;
q.push(s);
while(!q.empty())
{
int f=q.front();
q.pop();
for(int i=head[f];i;i=e[i].nxt)
{
int t=e[i].t;
if(!inque[t]&&e[i].val)
{
pre[t].bak=f;
pre[t].nxt=i;
if(t==to) return 1;
inque[t]=1;
q.push(t);
}
}
}
return 0;
}
//-----------------------------------
/*
priority_queue<node>q;
void dij()
{
for(int i=1;i<=n;i++) dis[i]=INF;
dis[s]=0;
q.push((node){0,s});
while(!q.empty())
{
node x=q.top();
q.pop();
int f=x.now;
if(vis[f]) continue;
vis[f]=1;
for(int i=head[f];i;i=e[i].nxt)
{
int t=e[i].t;
if(dis[t]>dis[f]+e[i].v)
{
dis[t]=dis[f]+e[i].v;
q.push((node){dis[t],t});
}
}
}
}
*/
//---------------------------------
int EK()
{
int ans=0;
while(bfs())
{
int minn=INF;
for(int i=to;i!=s;i=pre[i].bak) minn=min(minn,e[pre[i].nxt].val);
for(int i=to;i!=s;i=pre[i].bak)
{
e[pre[i].nxt].val-=minn;
e[pre[i].nxt^1].val+=minn;
}
ans+=minn;
}
return ans;
}
//-----------------------------------
}
using namespace lovespace;
void add(int f,int t,int v)
{
e[++head_size].f=f;
e[head_size].t=t;
e[head_size].val=v;
e[head_size].nxt=head[f];
head[f]=head_size;
}
ll read()
{
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
void print(ll x)
{
if(x>9) print(x/10);
putchar(x%10+'0');
}
int main()
{
n=read(),m=read(),s=read(),to=read();
for(int i=1;i<=m;i++)
{
int u,v,z;
u=read(),v=read(),z=read();
add(u,v,z);
add(v,u,0);
}
print(EK());
return 0;
}