[POJ 1273]Drainage Ditches(Edmond-Krap算法和Dinic算法求最大流)

自NOIP 2014结束之后将近一个星期没撸题了,现在开始搞省选,发个水水的裸网络流题解吧。

题目链接:http://poj.org/problem?id=1273

裸网络流,模板题。

1、Edmond_Karp算法

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <queue>

#define MAXV 220
#define MAXE 220
#define INF 0x3f3f3f3f

using namespace std;

int n,m;
int cap[MAXV][MAXV],flow[MAXV][MAXV]; //容量、流量
int a[MAXV];
int last[MAXV];

int EdmondsKarp(int s,int t) //EK算法求s到t的最大流
{
    int sum=0;
    queue<int>q;
    while(1)
    {
        while(!q.empty()) q.pop();
        q.push(s);
        memset(a,0,sizeof(a));
        a[s]=INF;
        while(!q.empty()) //找增广路
        {
            int u=q.front();
            q.pop();
            for(int v=1;v<=m;v++)
            {
                if(!a[v]&&flow[u][v]<cap[u][v])
                {
                    last[v]=u;
                    q.push(v);
                    a[v]=min(a[u],cap[u][v]-flow[u][v]);
                }
            }
        }
        if(a[t]==0) //找不到增广路,则已经找到最大流
            break;
        sum+=a[t]; //加上这次增广得到的流量
        for(int i=t;i!=s;i=last[i]) //根据增广路的链表顺着更新
        {
            flow[last[i]][i]+=a[t];
            flow[i][last[i]]-=a[t];
        }
    }
    return sum;
}

int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(cap,0,sizeof(cap));
        memset(flow,0,sizeof(flow));
        for(int i=1;i<=n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            cap[u][v]+=w;
        }
        printf("%d\n",EdmondsKarp(1,m));
    }
    return 0;
}

2、Dinic算法快速求网络流

#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
#include <deque>
#include <cstring>

#define mem(array,num) memset(array,num,sizeof(array))
#define MAXE 300
#define INF 0x3f3f3f3f

using namespace std;

int G[MAXE][MAXE];
bool visit[MAXE];
int Layer[300]; //Layer[i]=点i所在层数
int n,m;

bool CountLayer() //BFS对图进行分层
{
    int layer=0;
    deque<int>q;
    mem(Layer,-1); //初始化所有层数都为-1
    Layer[1]=0; //点1层数为0
    q.push_back(1); //点1入队
    while(!q.empty())
    {
        int now=q.front();
        q.pop_front();
        for(int j=1;j<=m;j++)
        {
            if(G[now][j]>0&&Layer[j]==-1) //now->j有剩余容量且j还没被访问过
            {
                Layer[j]=Layer[now]+1;
                if(j==m) return true; //分层到达了汇点即可
                else q.push_back(j);
            }
        }
    }
    return false; //到达不了汇点,返回false
}

int Dinic()
{
    int i,s,maxFlow=0;
    deque<int>q; //栈,DFS用
    while(CountLayer()) //只要能分层
    {
        q.push_back(1); //源点入栈
        mem(visit,0);
        visit[1]=true;
        while(!q.empty())
        {
            int top=q.back();
            if(top==m) //top是汇点
            {
                int minC=INF; //在栈中找容量最小的边
                int SminC; //容量最小的边的起点
                for(int i=1;i<q.size();i++)
                {
                    int vs=q[i-1];
                    int ve=q[i];
                    if(G[vs][ve]>0)
                    {
                        if(minC>G[vs][ve]) //更新最小容量边
                        {
                            minC=G[vs][ve];
                            SminC=vs;
                        }
                    }
                }
                //增广,改图
                maxFlow+=minC;
                for(int i=1;i<q.size();i++)
                {
                    int vs=q[i-1];
                    int ve=q[i];
                    G[vs][ve]-=minC; //减少边容量
                    G[ve][vs]+=minC; //增加反向边
                }
                while(!q.empty()&&q.back()!=SminC) //退栈直到SminC成为栈顶,这样方便DFS
                {
                    visit[q.back()]=false;
                    q.pop_back();
                }
            }
            else //top不是汇点
            {
                int i;
                for(i=1;i<=m;i++)
                {
                    if(G[top][i]>0&&Layer[i]==Layer[top]+1&&!visit[i]) //只往下一层没有走过的节点走
                    {
                        visit[i]=1;
                        q.push_back(i);
                        break;
                    }
                }
                if(i>m) //找不到下一个点,则往回走
                    q.pop_back();
            }
        }
    }
    return maxFlow;
}

int main()
{
    while(cin>>n>>m) //n边m点
    {
        mem(G,0);
        for(int i=0;i<n;i++)
        {
            int u,v,c;
            cin>>u>>v>>c;
            G[u][v]+=c; //防止被坑,两点间可能有多条边,容量累加
        }
        cout<<Dinic()<<endl;
    }
    return 0;
}



时间: 2024-10-01 00:29:05

[POJ 1273]Drainage Ditches(Edmond-Krap算法和Dinic算法求最大流)的相关文章

POJ 1273 Drainage Ditches(网络流 最大流)

Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 55893   Accepted: 21449 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by

POJ 1273 Drainage Ditches (网络最大流)

http://poj.org/problem?id=1273 Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 55235   Accepted: 21104 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means

POJ 1273 Drainage Ditches 最大流

很裸的最大流问题,不过注意会有重边,o(╯□╰)o,被阴了WA了一发 还有就是要用long long #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include

POJ 1273 Drainage Ditches 网络流基础

Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage

POJ 1273 Drainage Ditches(初识网络流)

开始研究网络流了,看了两个晚上吧,今天总算动手实践一下,有了更深的理解 总结一下:在最大流中,容量与实际流量满足3点: 1.实际流量<=容量 2.任意两点之间   : 流量(a->b)==流量(b->a) 3.流量守恒原则   :从s流出的流量 == t流入的流量 一.为什么叫增广路,因为在所有的流量网络中,会存在一个残量,所以在整个残量网络中,找到一个最小值,加到所有的流量线路里,便叫增广. 二.为什么要修改反向流量,因为在更新流量网时,当前选择的并不一定就是最优解,比如u->v

hdu 1532 poj 1273 Drainage Ditches (最大流)

Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 55276   Accepted: 21122 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by

POJ 1273 Drainage Ditches(我的EK算法模板)

题意:给你n条边,目标位置t:接下来是每条边,包括起点,终点,容量: 感想:第一道最大流的代码,这道题是我更深地理解了Ek算法,不过这道题有个超坑的情况,那就是出现重边的情况==! 思路:EK算法 AC代码: #include<stdio.h> #include<string.h> #include<algorithm> #include<queue> using namespace std; #define INF 100000000 #define N

poj 1273 Drainage Ditches(最大流)

http://poj.org/problem?id=1273 Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 62708   Accepted: 24150 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means

poj 1273 Drainage Ditches (最大流入门)

1 /****************************************************************** 2 题目: Drainage Ditches(POJ 1273) 3 链接: http://poj.org/problem?id=1273 4 题意: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条 5 水渠,给出这n条水渠所连接的池塘和所能流过的水量,求水 6 渠中所能流过的水的最大容量.水流是单向的. 7 算法: 最大流之增广路(入门)