网络流问题
最大流问题
在一张有向图中存在一个源点和汇点,图中的每一条边都有一个最大流量负载值,我们要求的是网络中从源点到汇点的最大流量值。
定理:在残量网络中当不存在一条从源点到汇点的增广路时,网络达到最大流。
基本算法
EK
int n,m,s,t,ans,cnt=-1;
int prenode[N],preedge[N],flow[N],head[N];
bool use[N];
queue<int>q;
struct Edge{
int pre,to,val;
}edge[N<<2];
void addedge(int fr,int to,int val){
edge[++cnt].pre=head[fr];edge[head[fr]=cnt].to=to;edge[cnt].val=val;
}
int bfs(){
memset(use,0,sizeof use);
use[s]=1;flow[s]=IFF;
q.push(s);
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[i];i+1;i=edge[i].pre){
int to=edge[i].to;
if(use[to]||!edge[i].val) continue;
use[to]=1;
prenode[to]=now;preedge[to]=i;flow[to]=min(flow[now],edge[i].val);
if(to==t) return flow[to];
}
}
return 0;
}
/*int dfs(int now,int val){
if(now==t||val==0) return val;
for(int i=head[now];i+1;i=edge[i].pre){
int to=edge[i].to;
if(use[to]) continue;
use[to]=1;
int op=dfs(to,min(val,edge[i].val));
edge[i].val-=op;edge[i^1]+=op;
if(op) return op;
use[to]=0;
}
return 0;
}*/
int main(){
while(!q.empty()) q.pop();
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);addedge(b,a,0);
}
int nowflow;
while(nowflow=bfs()){
ans+=nowflow;
for(int i=t;i!=s;i=prenode[i]){
int e=preedge[i];
edge[e].val-=nowflow;
edge[e^1].val+=nowflow;
}
}
}
D i n i c Dinic Dinic
int n,m,cnt=-1,ans;
int cur[N],dis[N],head[N];
queue<int >q;
struct Edge{
int pre,to,val;
}edge[N<<1];
void addedge(int fr,int to,int val){
edge[++cnt].pre=head[fr];edge[head[fr]=cnt].to=to;edge[cnt].val=val;
}
bool bfs(){
memset(use,0,sizeof use);
memset(dis,-1,sizof dis);
use[s]=1;dis[s]=0;
q.push(s);
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[now];i+1;i=edge[i].pre){
int to=edge[i].to;
if(dis[to]!=-1||!edge[i].val) continue;
dis[to]=dis[now]+1;
}
}
return dis[t]!=-1;
}
int dfs(int now,int val){
if(now==t||val==0) return val;
for(int& i=cur[i];i+1;i=edge[i].pre){
int to=edge[i].to;
if(dis[now]+1!=dis[to]) continue;
int nowflow=dfs(to,min(val,edge[i].val));
edge[i].val-=nowflow;edge[i^1].val+=nowflow;
if(nowflow) return nowflow;
}
return 0;
}
int main(){
while(!q.empty()) q.pop();
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;++i){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);addedge(b,a,0);
}
while(bfs()){
int nowflow;
while(nowflow=dfs(s,IFF)) ans+=nowflow;
}
}
费用流问题
int n,m,s,t,ans;
int dis[N],prenode[N],predge[N],head[N],flow[N];
bool use[N];
queue<int>q;
struct Edge{
int pre,to,f,val;
}edge[N<<1];
void addedge(int fr,int to,int val,int f){
edge[++cnt].pre=head[fr];edge[head[fr]=cnt].to=to;
edge[cnt].to=to;edge[cnt].val=val;
edge[cnt].f=f;head[fr]=cnt;
}
bool spfa(){
memset(use,0,sizeof use);
memset(dis,-1,sizeof dis);
while(!q.empty()) q.pop();
dis[s]=0;use[s]=1;flow[s]=IFF;
q.push(s);
while(!q.empty()){
int now=q.front();q.pop();
for(int i=head[now];i+1;i=edge[i].pre){
int to=edge[i].to;
if(!edge[i].val) continue;
if(dis[i]==-1||dis[now]+edge[i].f<dis[to]){
flow[to]=min(flow[now],edge[i].val);
dis[to]=dis[now]+edge[i].f;
prenode[to]=now;
predge[to]=i;
if(!use[to]) {
q.push(to);
use[to]=1;
}
}
if(to==t) return 1;
}
}
return 0;
}
int main(){
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;++i){
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
addedge(a,b,c,d);addedge(b,a,0,-d);
}
while(spfa()){
ans+=flow[t]*dis[t];
for(int i=t;i!=s;i=prenode[i]){
int e=predge[i];
edge[e].val+=e;
edge[e^1].val-=e;
}
}
}