HDU 1532 Drainage Ditches(最大流入门题目_Edmonds-Karp 增广路算法)

本文详细介绍了网络流中的E-K增广路算法,解释了有向图、边容量、流函数等基本概念,以及如何通过寻找增广路径来最大化网络流。提供了HDU1532的代码示例,展示了算法的具体实现。

 一个网络G=(V,E)是一张有向图,图中每条有向边(x,y)\in E都有一个给定的权值c(x,y),成为边的容量。特别地,若(x,y)\notin Ec(x,y)=0。图中还有两个指定的特殊点S\in VT\in V (S\neq T)分别称为源点和汇点。

f(x,,y)是定义在节点二元组(x\in V,y\in V)的实数函数,且满足:

1. f(x,y)\leq c(x,y)

2. f(x,y)=-f(y,x)

3. \forall x\not \neq S,x\neq T,\sum \left ( u,x \right )\in E \ f(u,x)=\sum (x,v)\in E\ f(x,v)

f称为网络的流函数。对于(x,y)\in E,f(x,y)称为边的流量,c(x,y)-f(x,y)成为这个边的剩余流量。

\sum (s,v)\in f(s,v)称为整个网络的流量(其中S表示源点)。

E-K算法只考虑图中所有f(x,y)<c(x,y)的边,用BFS找到任意一条从ST的路径,同时计算出路径上各边的剩余容量的最小值minf,则网络的流量就可以增加到minf。 

E-K增广路算法的时间复杂度为O(nm^{2}),然而在实际应用中则远远到不到这个上界,效率较高,一般能够处理10^{3}-10^{4}规模的网络。

简单附HDU1532的代码:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Pair pair<int,int>
#define int long long
#define fir first
#define sec second
const double eps=1e7;
namespace fastIO{
  #define BUF_SIZE 100000
  #define OUT_SIZE 100000
  //fread->read
  bool IOerror=0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
  inline char nc(){
    static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
      if(p1==pend){
        p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);
        if(pend==p1){IOerror=1;return -1;}
      }
      return *p1++;
  }
  inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
  template<class T> inline bool read(T &x){
    bool sign=0;char ch=nc();x=0;
    for(;blank(ch);ch=nc());
    if(IOerror)return false;
    if(ch=='-')sign=1,ch=nc();
    for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
    if(sign)x=-x;
    return true;
  }
  inline bool read(double &x){
    bool sign=0;char ch=nc();x=0;
    for(;blank(ch);ch=nc());
    if(IOerror)return false;
    if(ch=='-')sign=1,ch=nc();
    for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
    if(ch=='.'){double tmp=1; ch=nc();for(;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');}
      if(sign)x=-x;return true;
  }
  inline bool read(char *s){
    char ch=nc();
    for(;blank(ch);ch=nc());
    if(IOerror)return false;
    for(;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
    *s=0;
    return true;
  }
  inline bool read(char &c){
    for(c=nc();blank(c);c=nc());
    if(IOerror){c=-1;return false;}
    return true;
  }
  template<class T,class... U>bool read(T& h,U&... t){return read(h)&&read(t...);}
  #undef OUT_SIZE
  #undef BUF_SIZE
};using namespace fastIO;using namespace std;
const int N=2010,M=20010;
const int mod=1e9+7;

int head[N],ver[M],edge[M],Next[M],v[N],incf[N],pre[N];
int n,m,s,t,tot,maxflow;

void add(int x,int y,int z){
  ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
  ver[++tot]=x,edge[tot]=0,Next[tot]=head[y],head[y]=tot;
}
bool bfs(){
  memset(v,0,sizeof v);
  queue<int>q;
  q.push(s);v[s]=1;
  incf[s]=inf;//增广路各边的最小剩余容量
  while(q.size()){
    int x=q.front();q.pop();
    for(int i=head[x];i;i=Next[i]){
      if(edge[i]){
        int y=ver[i];
        if(v[y])continue;
        incf[y]=min(incf[x],edge[i]);
        pre[y]=i;
        q.push(y),v[y]=1;
        if(y==t)return 1;
      }
    }
  }
  return 0;
}

void update(){
  int x=t;
  while(x!=s){
    int i=pre[x];
    edge[i]-=incf[t];
    edge[i^1]+=incf[t];
    x=ver[i^1];
  }
  maxflow+=incf[t];
}
signed main(){
  while(read(m,n)){
    memset(head,0,sizeof head);
    s=1;t=n;tot=1;maxflow=0;
    for(int i=1;i<=m;i++){
      int x,y,c;read(x,y,c);
      add(x,y,c);
    }
    while(bfs())update();
    printf("%lld\n",maxflow);
  }
  return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值