首页 > 代码库 > POJ 1273 Drainage Ditches(初识网络流)

POJ 1273 Drainage Ditches(初识网络流)

开始研究网络流了,看了两个晚上吧,今天总算动手实践一下,有了更深的理解

总结一下:在最大流中,容量与实际流量满足3点:

1.实际流量<=容量

2.任意两点之间   : 流量(a->b)==流量(b->a)

3.流量守恒原则   :从s流出的流量 == t流入的流量


一、为什么叫增广路,因为在所有的流量网络中,会存在一个残量,所以在整个残量网络中,找到一个最小值,加到所有的流量线路里,便叫增广。


二、为什么要修改反向流量,因为在更新流量网时,当前选择的并不一定就是最优解,比如u->v 流量是20,下一次选择时,如果选择 v->u 这个边,就没什么意义了,就等价于刚才的流量网络取消了u->v这条支流。用网上一位神牛的博客里的一句话就是:给程序一个后悔的机会。膜拜大神。。。


EK算法:时间复杂度O(V*E*E),BFS查找


Drainage Ditches  基础增广算法题目

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
const int N = 210;
#define MIN -99999999
#define MAX 1e6

using namespace std;
int max(int a,int b)
{if(a>b)return a;else return b;}
int min(int a,int b)
{if(a<b)return a;else return b;}
int c[N][N];//容量网络
int f[N][N];//实际流量网络
int p[N]; // 增广路径
int re[N];//残亮网络
int n,m;
void init()
{
    for(int i = 0;i<=n;i++)
    {
        for(int j = 0;j<=n;j++)
        {
            c[i][j] = f[i][j] = 0;
        }
    }
}
void EK(int s,int t)
{
    queue<int>q;
    while(q.empty()==false) q.pop();
    int sum = 0;
    while(1)
    {
        memset(re,0,sizeof(re));//注意,每次循环都要初始残亮网络
        re[s] = MAX;
        p[s] = -1;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            for(int i = 1;i<=t;i++) //更新残亮网络,并记录增广路径
            {
                if(!re[i]&&f[u][i] < c[u][i])
                {
                    q.push(i);
                    p[i] = u;
                    re[i] = min(re[u], c[u][i]-f[u][i]);
                    //整个网络的最小残量
                }
            }
        }
        if(re[t]==0) break;
        for(int st = t;st!=s;st = p[st])
        {
            f[p[st]][st] += re[t]; //更新正向流量
            f[st][p[st]] -= re[t]; //更新反向流量
        }
       // printf("re[t] = %d\n",re[t]);
        sum += re[t];
    }
    printf("%d\n",sum);
}
int main()
{
    int a,b,w;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i = 0;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&w);
            c[a][b] +=  w;
        }
        EK(1,m);5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
        printf("%d\n",MIN);
    }
    return 0;
}