网络流基础模板

                                                              Drainage Ditches


题目链接:Click Here~

题意解析:

    最近忙,好久没写了博客了。因为是第一次写网络流,所以写一下纪念一下。

    题意很简单,就是网络流中的最大流的定义。给出n条边,m个顶点。问你其中可以得到的最大流是多少。

算法分析:

    典型的最大流算法。我用的是EdmonsKarp算法,先用一个简单的。虽然,另外两个也学了。要注意检查一个点是否重复进入队列,还有就是因为改题的流量存在着0,所以,不能用流量是否为0来判断。一开始我一直错,后来才发现的,所以,我另设了一个变量。具体过程自己看代码吧。还有要注意重边的处理。其他的就是模板的事情了。


#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;

class EdmondsKarp{
   public:
      static const int N = 200+5;
      static const int INF = 1e8;
      int n,m,f,a[N],p[N],cap[N][N],flow[N][N];
      void Init(int n,int m){
          f = 0;
          this->n = n;
          this->m = m;
          memset(cap,0,sizeof(cap));
          memset(flow,0,sizeof(flow));
      }
      void AddEdge(int u,int v,int w);
      void Edmondskarp(int s,int t);
};
void EdmondsKarp::AddEdge(int u,int v,int w)
{
    cap[u][v] += w;                 //注意重边
}
void EdmondsKarp::Edmondskarp(int s,int t)
{
     queue<int> q;
     while(1){
         memset(a,0,sizeof(a));
         memset(p,-1,sizeof(p));     //注意破栈
         a[s] = INF;
         q.push(s);
         while(!q.empty()){
            int u = q.front();
            q.pop();
            for(int v = 1;v <= m;++v){
              if(!a[v]&&p[v]==-1&&cap[u][v]>flow[u][v]){
                  p[v] = u;
                  q.push(v);
                  a[v] = min(a[u],(cap[u][v]-flow[u][v]));
              }
            }
         }
         if(a[t]==0)
            break;
         for(int u = t;u != s;u = p[u]){
            flow[p[u]][u] += a[t];
            flow[u][p[u]] -= a[t];
         }
         f += a[t];
     }
     printf("%d\n",f);
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        EdmondsKarp edmonds;
        edmonds.Init(n,m);
        int u,v,w;
        for(int i = 0;i < n;++i){
           scanf("%d%d%d",&u,&v,&w);
           edmonds.AddEdge(u,v,w);
        }
        edmonds.Edmondskarp(1,m);
    }
    return 0;
}

还有同样的题,就是这题不需要另外判断一点是否重复入队列。因为,改题的流量大于0.

题目链接:Click Here~

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;

class EdmonsKarp{
   public:
      static const int N = 20;
      static const int INF = 1e4;
      void Init(int n,int m);
      void AddEdge(int u,int v,int w);
      int Edmonskarp(int s,int t);
   private:
      int n,m,f,a[N],p[N],flow[N][N],cap[N][N];
};
inline void EdmonsKarp::Init(int n,int m)
{
    f = 0;
    this->n = n;
    this->m = m;
    memset(cap,0,sizeof(cap));
    memset(flow,0,sizeof(flow));
}
inline void EdmonsKarp::AddEdge(int u,int v,int w)
{
    cap[u][v] += w;
}
int EdmonsKarp::Edmonskarp(int s,int t)
{
     queue<int> q;
     while(1){
//        memset(p,-1,sizeof(p));
        memset(a,0,sizeof(a));
        a[s] = INF;
        q.push(s);
        while(!q.empty()){
           int u = q.front();
           q.pop();
           for(int v = 1;v <= n;++v){
             if(!a[v]&&cap[u][v]>flow[u][v]){
                p[v] = u;
                q.push(v);
                a[v] = min(a[u],cap[u][v]-flow[u][v]);
             }
           }
        }
        if(a[t]==0)
          break;
        for(int u = t;u != s;u = p[u]){
           flow[p[u]][u] += a[t];
           flow[u][p[u]] -= a[t];
        }
        f += a[t];
     }
     return f;
}
int main()
{
    int T,n,m;
    scanf("%d",&T);
    for(int kase = 1;kase <= T;kase++)
    {
        int x,y,w;
        EdmonsKarp edmons;
        scanf("%d%d",&n,&m);
        edmons.Init(n,m);
        for(int i = 0;i < m;++i){
           scanf("%d%d%d",&x,&y,&w);
           edmons.AddEdge(x,y,w);
        }
        printf("Case %d: %d\n",kase,edmons.Edmonskarp(1,n));
    }
    return 0;
}


 



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值