ネットワークフロー(研究ノート)
(PS:この記事は純粋の使用を検討し、子供の靴のための姿を見たいと思っては非常に友好的ではありません)
私たちは、それぞれのチューブは、節水フローの最大負荷を持って、ご自宅の水供給ネットワークへの水工場は複雑な有向グラフであると想像します。水道水をオンにしないでください、あなたの家は、水なしです。しかし、水の流れを受信するためにも、必死になってあなたの家庭内の水道管網に水道場合(すべての後に、各パイプの限られた伝送容量)の上限値です。あなたはあなたが得ることができますどのくらいの水を知りたい、これは、ネットワークフロー問題があります。
あなたは、基本的なネットワークフローアルゴリズムを学ぶ際にここで、私は、このようなものを斜め対称ああ、ああ漢漢のフロー保存などの直接の定理の多くを投げるのが好きではありません、私は、これらは重要ではないと信じています。
ここで私は分類されているさまざまな問題に従っていませんでしたが、異なるアルゴリズムを検討します。
-
EKアルゴリズム(エドモンズカープアルゴリズム)
- これは一方通行BFSベースの増強アルゴリズムです。
事前知識:
ネットワークフロー増強パスに現在の総流量が増加するように、パスC(s、t)は、存在する場合、このパスはパスを増強呼ばれます。
増補道路網が存在しない場合は見つけるのは簡単、あなたは、ネットワーク上のトラフィックの最大流量を得ることができます。
だから、求めている最大フロー問題が見つかりまでの経路を増強見つけるために、引き続きパスの問題を増大させるために変換されます。
それがどのように動作しますか?我々は、我々が最小残量変更C(S、T)のパスを見つける必要があり、時間がそれぞれTを実行したとき、0側よりも大きい残存量(現在の流量マイナス側の総容量)によって、BFS sから開始しますこのパスフィル:すなわち、各側は、最小残差を減算されます。
我々はこれまでのところ、そのようなパスが存在しないことを見つけるまで。
だからここに質問がされています。現在のパス上の残留物の量を減らすために、パスを増強する場合、あなたは別の道を見つけてきましたが、残留トンの量がまだ利用可能ポイントから、あなたは見つけるでしょうあなたは、最適解を得ることができません。さて、ここでのマップ海賊:
例えば:あなたはS->、3-> 5>トンを発見した、流量は10です
あなたが第一の流路を差し引く、検索S-> 4 - > 5 - >トンだ、新しい流量は35です
しかし、あなたは、S-> 3 - > tとS-> 4 - > 5>それぞれトン、10、45になるように流量、明らかに大きいを検索することができますを見つけます。
可如果你不做任何处理的话,你会发现你在搜过s->3->5->t后,你永远不会再搜到3了,也就不会找到s->3->t这条路径了。
那么怎么办呢?我们考虑对每条边加一条初始流量为0的反向边。
当我们先搜s->3->5->t时,我们把正边减去最大流量,反边加上最大流量。
这就告诉了第二条路径s->4->5->t,在到达节点5时,其实有10的流量是通过3留过来的,那么如果把这10流量返回去,再次从3开始跑,若能到达t则相当于找到了一条增广路。进而为第二条路径增大了10残量。
是不是很NB,下面放上code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=10010;
const int maxm=100010;
const int inf=1<<30;
struct node
{
int to,next,dis;
}g[maxm*2];
int head[maxn],cnt=1;
struct P
{
int edge,from;
}pre[maxn];
int ans;
int n,m,s,t;
inline int read()
{
int 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*10+ch-'0';ch=getchar();}
return x*f;
}
inline void addedge(int u,int v,int dis)
{
g[++cnt].next=head[u];
g[cnt].to=v;
g[cnt].dis=dis;
head[u]=cnt;
}
bool vis[maxn];
bool bfs()
{
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));
queue<int>q;
q.push(s);
vis[s]=1;
while(q.size())
{
int u=q.front();q.pop();
for(int i=head[u];i;i=g[i].next)
{
int v=g[i].to;
if(!vis[v]&&g[i].dis)
{
pre[v].edge=i;
pre[v].from=u;
if(t==v)return 1;
vis[v]=1;
q.push(v);
}
}
}
return 0;
}