HDU 1532 Drainage Ditches 网络流模板题(Dinic)

题目大意:

就是给出一个DAG, 源点是1, 汇点是M, 给出每条边的容量, 询问1到M的最大流


大致思路:

网络流模板题...

第一次写网络流, 记一下


代码如下:

Result  :  Accepted     Memory  : 1576 KB     Time  :  0 ms

/*
 * Author: Gatevin
 * Created Time:  2015/12/4 22:08:42
 * File Name: Yukinoshita_Yukino.cpp
 */
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
typedef long long lint;

/*
 * 第一道网络流的题
 * 使用Dinic模板
 */

#define maxn 222
//maxn : 点数
#define maxm 222
//maxm : 无向边边数

struct Edge//有向边u->v容量是cap
{
    int u, v, nex, cap;
    Edge(){}
    Edge(int _u, int _v, int _nex, int _cap)
    {
        u = _u, v = _v, nex = _nex, cap = _cap;
    }
};

Edge edge[maxm << 1];
int E;
int head[maxn];

void add_Edge(int u, int v, int c)//第一条边下标必须是偶数
{
    edge[++E] = Edge(u, v, head[u], c);
    head[u] = E;
    edge[++E] = Edge(v, u, head[v], 0);
    head[v] = E;
}

int N, M;

int dep[maxn];

bool bfs(int start, int end)
{
    int Q[maxn];
    int l, r;
    l = r = 0;
    memset(dep, -1, sizeof(dep));
    Q[r++] = start;
    dep[start] = 0;
    while(l != r)
    {
        int u = Q[l++];
        if(l == maxn) l = 0;
        for(int i = head[u]; i + 1; i = edge[i].nex)
        {
            int v = edge[i].v;
            if(edge[i].cap > 0 && dep[v] == -1)
            {
                dep[v] = dep[u] + 1;
                Q[r++] = v;
                if(r >= maxn) r = 0;
                if(v == end) return 1;
            }
        }
    }
    return 0;
}

int dinic(int start, int end)
{
    int res = 0;
    int top;
    int stack[maxn];//stack为存储当前增广路的栈
    int cur[maxn];
    while(bfs(start, end))//存在增广路就继续增广
    {
        memcpy(cur, head, sizeof(head));
        int u = start;
        top = 0;
        while(1)
        {
            if(u == end)//对增广路上的流量做减法并且对反向边容量进行扩张
            {
                //int min = INF;
                int min = 1e9;
                int loc;
                for(int i = 0; i < top; i++)
                    if(min > edge[stack[i]].cap)
                    {
                        min = edge[stack[i]].cap;
                        loc = i;
                    }
                for(int i = 0; i < top; i++)
                {
                    edge[stack[i]].cap -= min;
                    edge[stack[i] ^ 1].cap += min;
                }
                res += min;
                top = loc;
                u = edge[stack[top]].u;
            }
            for(int i = cur[u]; i + 1; cur[u] = i = edge[i].nex)
                if(edge[i].cap != 0 && dep[u] + 1 == dep[edge[i].v])//寻找是否有往下一层的路
                    break;
            if(cur[u] != -1)//有下一层的路
            {
                stack[top++] = cur[u];
                u = edge[cur[u]].v;
            }
            else//不能继续向下走了, 回溯
            {
                if(top == 0) break;
                dep[u] = -1;
                u = edge[stack[--top]].u;
            }
        }
    }
    return res;
}


int main()
{
    while(scanf("%d %d", &N, &M) != EOF)
    {
        memset(head, -1, sizeof(head));
        E = -1;
        
        int u, v, c;
        for(int i = 0; i < N; i++)
        {
            scanf("%d %d %d", &u, &v, &c);
            add_Edge(u, v, c);
        }
        printf("%d\n", dinic(1, M));
    }
    return 0;
}

 

你可能感兴趣的:(HDU,网络流,dinic,Drainage,Ditches,1532)