POJ 1273-Drainage Ditches(网络流_最大流_ISAP()算法和EK()算法)

Drainage Ditches

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 58538   Accepted: 22485

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 ditches so that Bessie‘s
clover patch is never covered in water. Instead, the water is drained to a nearby stream. Being an ace engineer, Farmer John has also installed regulators at the beginning of each ditch, so he can control at what rate water flows into that ditch.

Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network.

Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.

Input

The input includes several cases. For each case, the first line contains two space-separated integers, N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of ditches that Farmer John has dug. M is the number of intersections points
for those ditches. Intersection 1 is the pond. Intersection point M is the stream. Each of the following N lines contains three integers, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) designate the intersections between which this ditch flows. Water will flow
through this ditch from Si to Ei. Ci (0 <= Ci <= 10,000,000) is the maximum rate at which water will flow through the ditch.

Output

For each case, output a single integer, the maximum rate at which water may emptied from the pond.

Sample Input

5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10

Sample Output

50

题意:有n条路,m个点,让你求出以1为源点,m为汇点的最大流;

思路:典型的最大流增光路的算法。当且仅当残量网络中不存在s-t有向道路(增广路)时,此时的流是从s到t的最大流;

ISAP()

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
using namespace std;
const int inf=0x3f3f3f3f;
//head存储前向星的有相同起点的弧,num存储各层剩余节点数目,d存储各节点的层数,cur存储当前弧,pre存储路径,即当前节点的上一个节点,用于回溯。
int head[1010],num[1010],d[1010],cur[1010],n,m,cnt,s,t,q[100010],nv,pre[1010];
int maxint=inf;
struct node
{
    int v,cap;
    int next;
}edge[10010];
void add(int u,int v,int cap)
{
    //加正向弧
    edge[cnt].v=v;
    edge[cnt].cap=cap;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    //加反向弧
    edge[cnt].v=u;
    edge[cnt].cap=0;
    edge[cnt].next=head[v];
    head[v]=cnt++;
}
void bfs()//用bfs对每个节点进行分层
{
    //算法执行之前需要用 BFS 初始化  d  数组,方法是从  t  到  s  逆向进行
    int i,j;
    memset(num,0,sizeof(num));
    memset(d,-1,sizeof(d));
    int f1=0,f2=0;
    q[f1++]=t;//从
    d[t]=0;
    num[0]=1;
    while(f2<=f1){
        int u=q[f2++];
        for(i=head[u];i!=-1;i=edge[i].next){
            int v=edge[i].v;
            if(d[v]!=-1) continue;
            d[v]=d[u]+1;//此节点的层数是上一节点的下一层
            num[d[v]]++;//该层数的节点数+1
            q[f1++]=v;
        }
    }

}
void isap()
{
    memcpy(cur,head,sizeof(cur));
    bfs();
    int flow=0,u=pre[s]=s,i;
    while(d[s]<nv){//如果d[s]大于nv,说明有断层
        if(u==t){
            int f=maxint,pos;
            for(i=s;i!=t;i=edge[cur[i]].v){//找该路上的最少残余流量
                if(f>edge[cur[i]].cap){
                    f=edge[cur[i]].cap;
                    pos=i;
                }
            }
            for(i=s;i!=t;i=edge[cur[i]].v){//更新,将该路上的所有流量-最少参与流量
                edge[cur[i]].cap-=f;
                edge[cur[i]^1].cap+=f;
            }
            flow+=f;//加入总流量
            u=pos;
        }
        for(i=cur[u];i!=-1;i=edge[i].next){
            if(d[edge[i].v]+1==d[u]&&edge[i].cap){
                break;
            }
        }
        if(i!=-1){//如果找到可行增广路,更新
            cur[u]=i;//更新当前弧
            pre[edge[i].v]=u;//更新路径
            u=edge[i].v;//回溯
        }
        else{
            if(--num[d[u]]==0) break;//gap优化
            int mind=nv;
            for(i=head[u];i!=-1;i=edge[i].next){//找最小层次
                if(edge[i].cap&&mind>d[edge[i].v]){
                    cur[u]=i;
                    mind=d[edge[i].v];
                }
            }
            d[u]=mind+1;
            num[d[u]]++;
            u=pre[u];
        }
    }
    printf("%d\n",flow);
}
int main()
{
    int i,a,b,c;
    while(~scanf("%d %d",&n,&m)){
        memset(head,-1,sizeof(head));
        cnt=0;
        while(n--){
            scanf("%d %d %d",&a,&b,&c);//加边
            add(a,b,c);
        }
        s=1;
        t=m;
        nv=t+1;
        isap();
    }
    return 0;
}

EK()

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <queue>
using namespace std;
#define inf  9999999999
int flow[210][210];
int maxflow[210],father[210],vis[210];
int max_flow;
int m,i;
void EK(int s,int e)
{
    queue<int >q;
    int u,v;
    while(1)
    {
        memset(maxflow,0,sizeof(maxflow));//每次寻找增广路径都将每个点的流入容量置为0;
        memset(vis,0,sizeof(vis));
        maxflow[s]=inf;//源点的流入量置为正无穷;
        q.push(s);//将源点压入队列;
        while(!q.empty())//当队列不为空
        {
            u=q.front();
            q.pop();
            for(v=s;v<=e;v++)
            {
                if(!vis[v]&&flow[u][v]>0)
                {
                    vis[v]=1;
                    father[v]=u;//记录下他的父亲方便反向更新
                    q.push(v);
                    maxflow[v]=min(maxflow[u],flow[u][v]);//当前点的容量为父亲点容量与边流量的较小者
                }
            }
            if(maxflow[e]>0)//如果找到了汇点并且汇点容量不为0则清空队列
            {
                while(!q.empty())
                    q.pop();
                break;
            }
        }
        if(maxflow[e]==0)//已经找不到到汇点的增光路经了,就退出整个循环
            break;
        for(i=e;i!=s;i=father[i])
        {
            flow[father[i]][i]-=maxflow[e];//正向更新
            flow[i][father[i]]+=maxflow[e];//反向更新
        }
        max_flow+=maxflow[e];//更新最大流
    }
}
int main()
{
    int n;
    int si,ei,ci;
    while(~scanf("%d %d",&n,&m))
    {
        max_flow=0;//最大流初始化;
        memset(flow,0,sizeof(flow));
        for(i=0;i<n;i++)
        {
            scanf("%d %d %d",&si,&ei,&ci);
            flow[si][ei]+=ci;
        }
        EK(1,m);
        printf("%d\n",max_flow);
    }
}
时间: 2024-10-25 07:04:17

POJ 1273-Drainage Ditches(网络流_最大流_ISAP()算法和EK()算法)的相关文章

NYOJ 323 &amp;&amp; HDU 1532 &amp;&amp; POJ 1273 Drainage Ditches (网络流之最大流入门)

链接:click here 题意:给出n个河流,m个点,以及每个河流的流量,求从1到m点的最大流量. 思路:最裸的网络流题目  意思就是求从源点到汇点的最大流. 第一道网络流,一边看着书上的介绍,一边敲下代码: 用的是网络流算法ford-fulkerson 题目数据量小,邻接表和邻接矩阵都可以过 代码: #include <ctype.h> //最大流 入门 #include <stdio.h> #include <vector> #include <stdlib

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 网络流基础

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 (网络流最大流基础 Edmonds_Karp算法)

Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 59219   Accepted: 22740 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 网络流最大流基础

Drainage Ditches Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 59176   Accepted: 22723 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 (网络流Dinic模板)

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

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