hdu 1532 Drainage Ditches (网络流两种方法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532



Drainage Ditches

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1507    Accepted Submission(s): 701

Problem 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

 

代码如下:                 Accepted                    596KB                     0ms

代码一(max_flow):

#include <iostream>
#include <queue>
#include <string.h>
#include <stdio.h>
using namespace std;
#define MAXN 205
#define INF 2110000000
#define MIN(x,y) (x<y?x:y)
int map[MAXN][MAXN];
int max_flow(int num,int map[][MAXN],int source,int sink)//参数含义:结点数量 网络 源点 汇点
{
    int pre[MAXN],min_flow[MAXN];//记录结点的父节点 当前路径中最小的一段的值,也即限制值
    int flow[MAXN][MAXN];//记录当前网络中的流
    int ans = 0 ;//最终结果
    memset(flow,0,sizeof(flow));
    while(1)//一直循环,直到不存在增广路径
    {
        queue<int> q;
        memset(pre,-1,sizeof(pre));
        q.push(source);
        pre[source] = -2;//源点的父节点需特殊标示
        min_flow[source] = INF;
        while(!q.empty())//BFS寻找增广路径
        {
            int temp = q.front();//出队列
			q.pop();
            for(int i = 0 ; i < num ; i++)//由结点temp往外扩展
            {
                if(pre[i] == -1 && flow[temp][i] < map[temp][i])
						//当结点i还未被探索到,并且还有可用流量
                {
                    q.push(i);//加入队列
                    pre[i] = temp;//标示父节点
                    min_flow[i] = MIN(min_flow[temp],map[temp][i]-flow[temp][i]);//求得min_flow
                }
            }
            if(pre[sink]!=-1)//sink的父节点不为初始值,说明BFS已经找到了一条路径
            {
                int k = sink;
                while(pre[k] >= 0)
                {
                    flow[pre[k]][k] +=min_flow[sink];//将新的流量加入flow
                    flow[k][pre[k]] -=min_flow[sink];
                    k = pre[k];
                }
                break;
            }
        }
        if(pre[sink] != -1) 
			ans+=min_flow[sink];
        else
			return ans;//不存在增广路径,返回
    }
}
int main()
{
    int m,n;//n流通数,m为节点数量
    while(~scanf("%d%d",&n,&m))
    {
        int a,b,cost;
        memset(map,0,sizeof(map));
        for(int i=0;i<n;i++)
        {
			scanf("%d%d%d",&a,&b,&cost);
            map[a-1][b-1]+=cost;//网络
        }
        printf("%d\n",max_flow(m,map,0,m-1));
    }
    return 0;
}


代码二(SAP):

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 3017;//点数的最大值
const int MAXM = 100017;//边数的最大值
const int INF = 0x3f3f3f3f;
struct Edge
{
    int to, cap, flow;
	int next;
}edge[MAXM];//注意是MAXM
int tol;
int head[MAXN];
int dep[MAXN],pre[MAXN],cur[MAXN];
int gap[MAXN];//gap[x]=y :说明残留网络中dep[i]==x的个数为y
void init()
{
    tol = 0;
    memset(head,-1,sizeof (head));
}
//加边,单向图三个参数,双向图四个参数
void addedge (int u,int v,int w,int rw=0)
{
    edge[tol].to = v;edge[tol].cap = w;
	edge[tol].next = head[u];
    edge[tol].flow = 0;
	head[u] = tol++;
    edge[tol].to = u;edge[tol].cap = rw;
	edge[tol]. next = head[v];
    edge[tol].flow = 0;head[v]=tol++;
}
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end, int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u = start;
    pre[u] = -1;
    gap[0] = N;
    int ans = 0;
    int i;
    while(dep[start] < N)
    {
        if(u == end)
        {
            int Min = INF;
            for( i = pre[u];i != -1; i = pre[edge[i^1]. to])
            {
                if(Min > edge[i].cap - edge[i]. flow)
                    Min = edge[i].cap - edge[i].flow;
            }
            for( i = pre[u];i != -1; i = pre[edge[i^1]. to])
            {
                edge[i].flow += Min;
                edge[i^1].flow -= Min;
            }
            u = start;
            ans += Min;
            continue;
        }
        bool flag =  false;
        int v;
        for( i = cur[u]; i != -1;i = edge[i].next)
        {
            v = edge[i]. to;
            if(edge[i].cap - edge[i].flow && dep[v]+1 == dep[u])
            {
                flag =  true;
                cur[u] = pre[v] = i;
                break;
            }
        }
        if(flag)
        {
            u = v;
            continue;
        }
        int Min = N;
        for( i = head[u]; i !=  -1; i = edge[i]. next)
        {
            if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
            {
                Min = dep[edge[i].to];
                cur[u] = i;
            }
        }
        gap[dep[u]]--;
        if(!gap[dep[u]]) 
			return ans;
        dep[u] = Min+1;
        gap[dep[u]]++;
        if(u != start) 
			u = edge[pre[u]^1].to;
    }
    return ans;
}
int main()
{
    int n, m;
	int a, b, w;
	int c, s, t;
	int i;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        init();//初始化     
        for(i = 1; i <= m; i++)//边数
        {
            scanf("%d%d%d",&a,&b,&w);
            addedge(a,b,w,0);
       //     addedge(b,a,w,0);
        }
		int ans = sap(1, n, n);
        printf("%d\n",ans);
    }
    return 0;
}


另附大牛的五份模板代码:
亲请点击:http://blog.csdn.net/acm_davidcn/article/details/5801277
此题纯粹是最大流的模板题 , 给最大流的初学者练习的题 .
5份: Ford-Fulkerson 邻接矩阵版本的 BFS 和 DFS 的模板和 Ford-Fulkerson 邻接表版本的 BFS 模板 , 还有 Dinic 的邻接矩阵和邻接表模板 , 共 5 个模板解此题 ,


 
 
 
 
 
 
 
 
 
 
 

你可能感兴趣的:(ACM,iostream,流量)