zoukankan      html  css  js  c++  java
  • 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 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

    题目大意:m条边,每条边都有一个流量值,n个点,求1到n的最大流量

    Dinic模板:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<queue>
    #include<algorithm>
    #define N 210
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    int G[N][N], vis[N], layer[N];
    int n;
    
    bool BFS()//分层处理
    {
        deque<int>Q;//定义双端队列
        memset(layer, -1, sizeof(layer));
        Q.push_back(1);//源点入队列(双端队列尾部增加一个元素x)
        layer[1] = 1;//标记源点
        while(!Q.empty())
        {
            int u = Q.front(), i;
            Q.pop_front();//删除双端队列中最前一个元素
            for(i = 1 ; i <= n ; i++)//遍历点判断是否能分层
            {
                if(G[u][i] > 0 && layer[i] == -1)//当u点到i点这条边有流量且i点尚未被分层
                {
                    layer[i] = layer[u] + 1;//则将i点分层
                    if(i == n)//当到达汇点时分层成功
                        return true;
                    else
                        Q.push_back(i);//否则继续
                }
            }
        }
        return false;
    }
    
    int Dinic()
    {
        int Maxflow = 0;
        while(BFS() == true)
        {
            deque<int>Q;
            memset(vis, 0, sizeof(vis));
            Q.push_back(1);
            vis[1] = 1;
            while(!Q.empty())
            {
                int v = Q.back(), i;
                if(v != n)
                {
                    for(i = 1 ; i <= n ; i++)
                    {
                        if(G[v][i] > 0 && layer[v] + 1 == layer[i] && !vis[i])//如果v到i有流量且i点是v点的增广路且点i未被访问过
                        {
                            vis[i] = 1;
                            Q.push_back((i));//点i进入队列(即点i属于增广路上的一个点)
                            break;
                        }
                    }
                    if(i > n)//如果遍历所有点后在下一层没有找到增广路,就退出本层继续寻找下一条
                        Q.pop_back();//删除双端队列中最后一个元素
                }//找增广路
                else
                {
                    int Minflow = INF, nv;
                    int len = Q.size();//进入队列中点的个数
                    for(int i = 1 ; i < len ; i++)
                    {
                        int x = Q[i - 1];//前一个点
                        int y = Q[i];//后一个点
                        if(Minflow > G[x][y])
                        {
                            Minflow = G[x][y];
                            nv = x;//nv记录前端点
                        }//查找最小值即增光流量
                    }
                    Maxflow += Minflow;
                    for(int i = 1 ; i < len ; i++) //更新流量
                    {
                        int x = Q[i - 1];
                        int y = Q[i];
                        G[x][y] -= Minflow;//更新正向
                        G[y][x] += Minflow;//反向增加
                    }
                    while(!Q.empty() && Q.back() != nv)
                        Q.pop_back();//出队
                }
            }
        }
        return Maxflow;
    }
    
    int main()
    {
        int a, b, c, m;
        while(~scanf("%d%d", &m, &n))
        {
            memset(G, 0, sizeof(G));
            while(m--)
            {
                scanf("%d%d%d", &a, &b, &c);
                G[a][b] += c;//处理重边
            }
            printf("%d
    ", Dinic());
        }
        return 0;
    }
    /*
    10 8
    1 2 10
    1 3 10
    2 4 20
    2 5 20
    3 6 20
    3 7 20
    4 8 30
    5 8 30
    6 8 30
    7 8 30
    */
    View Code

     邻接表+Dinic(仅供参考)

    #include<stdio.h>
    #include<algorithm>
    #include<queue>
    #include<string.h>
    #define INF 0x3f3f3f3f
    #define N 1010
    using namespace std;
    
    struct Edge
    {
        int u, v, next, flow;
    } edge[N * N];
    
    int layer[N], head[N], cnt;
    
    void Init()
    {
        memset(head, -1, sizeof(head));
        cnt = 0;
    }
    
    void AddEdge(int u, int v, int flow)
    {
        edge[cnt].u = u;
        edge[cnt].v = v;
        edge[cnt].flow = flow;
        edge[cnt].next = head[u];
        head[u] = cnt++;
    }
    
    bool BFS(int Start, int End)//分层
    {
        queue<int>Q;
        memset(layer, -1, sizeof(layer));
        Q.push(Start);
        layer[Start] = 1;
        while(!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            if(u == End)
                return true;
            for(int i = head[u] ; i != -1 ; i = edge[i].next)
            {
                int v = edge[i].v;
                if(layer[v] == -1 && edge[i].flow > 0)
                {
                    layer[v] = layer[u] + 1;
                    Q.push(v);
                }
            }
        }
        return false;
    }
    
    int DFS(int u, int Maxflow , int End)
    {
        if(u == End)
            return Maxflow;
        int uflow = 0;
        for(int i = head[u] ; i != -1 ; i = edge[i].next)
        {
            int v = edge[i].v;
            if(layer[v] == layer[u] + 1 && edge[i].flow > 0)
            {
                int flow = min(edge[i].flow, Maxflow - uflow);
                flow = DFS(v, flow, End);
                edge[i].flow -= flow;
                edge[i^1].flow += flow;
                uflow += flow;
    
                if(uflow == Maxflow)
                    break;
            }
        }
        if(uflow == 0)
            layer[u] = 0;
        return uflow;
    }
    
    int Dinic(int Start, int End)
    {
        int Maxflow = 0;
        while(BFS(Start, End))
            Maxflow += DFS(Start, INF, End);
        return Maxflow;
    }
    
    int main()
    {
        int m, n;
        while(~scanf("%d%d", &m, &n))
        {
            Init();
            int u, v, flow;
            while(m--)
            {
                scanf("%d%d%d", &u, &v, &flow);
                AddEdge(u, v, flow);
                AddEdge(v, u, 0);
            }
            printf("%d
    ", Dinic(1, n));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    穷举法和搜索法的统计三角形
    2015.5.21 Core Java Volume 1
    我喜欢出发
    MeshLab中画面在前面加个f的代码
    【axel帮助代码】为了在单位正方形里面画一个洞 ,网上获取了此代码。
    uniapp 发起网络请求
    qt 取进程列表,读写内存, 写字节集
    qt 注册热键
    qt 获取窗口句柄的线程id和进程id GetWindowThreadProcessId
    qt 向窗口发送消息,键盘输入事件
  • 原文地址:https://www.cnblogs.com/qq2424260747/p/4726627.html
Copyright © 2011-2022 走看看