zoukankan      html  css  js  c++  java
  • hdu 2549 Flow Problem 最大流

    hdu 2549 Flow Problem 最大流
    //hdu 2549 Flow Problem 最大流
    //简单最大流
    //EK算法居然比 同时找多条增广路的dinic算法还快
    //
    //dinic要注意找不到增广路的点的层次要标为-1
    //
    //具体看代码
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    
    using namespace std;
    
    #define INF (1<<30)
    #define N 25
    
    int map[N][N], fa[N];
    bool vis[N];
    
    bool bfs(int n)
    {
        memset(vis, false, sizeof(vis));
        memset(fa, -1, sizeof(fa));
        queue<int>que;
        que.push(1);
        vis[1] = true;
        while(!que.empty())     //广搜找增广路
        {
            int now = que.front();
            que.pop();
            vis[now] = true;
            for(int i = 1; i <= n; ++i)
            {
                if(vis[i] == false && map[now][i] > 0)
                {
                    vis[i] = true;
                    fa[i] = now;
                    if(i == n)
                        return true;
                    que.push(i);
                }
            }
        }
        return false;
    }
    
    
    void EK(int n, int m)
    {
        int ans = 0;
        while(bfs(n))   //找增广路
        {
            int min = INF;//找增广路的瓶颈,也就是找到这条增广路
            for(int i = n; i != 1; i = fa[i])   //留向汇点的流量
                min = map[fa[i]][i] < min ? map[fa[i]][i] : min;
    
            for(int i = n; i != 1; i = fa[i])
            {
                map[fa[i]][i] -= min;
                map[i][fa[i]] += min;   //建反向边
            }
            ans += min;
        }
        printf("%d\n", ans);
    }
    
    int main()
    {
        int n_case;
        scanf("%d", &n_case);
        for(int j = 1; j <= n_case; ++j)
        {
            printf("Case %d: ", j);
            int n, m;
            scanf("%d%d", &n, &m);
            memset(map, 0, sizeof(map));
            for(int i = 0; i < m; ++i)
            {
                int from, to, f;
                scanf("%d%d%d", &from, &to, &f);
                map[from][to] += f;
            }
            EK(n, m);
        }
        return 0;
    }
    dinic
    #define comein freopen("in.txt", "r", stdin);
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    #include <algorithm>
    using namespace std;
    
    
    #define INF 1<<30
    #define N 2000
    
    int eid;
    int head[N], to[N], cap[N], next[N];
    int level[N];
    
    void add_edge(int from, int t, int f)
    {
        to[eid] = t;
        cap[eid] = f;
        next[eid] = head[from];
        head[from] = eid++;
    
        to[eid] = from;   //建反向边
        cap[eid] = 0;
        next[eid] = head[t];
        head[t] = eid++;
    }
    
    bool bfs(int root, int n_point)     //残余网络分层
    {
        memset(level, -1, sizeof(level));
        queue<int>que;
        que.push(root);
        level[root] = 0;
        while(!que.empty())
        {
            root = que.front();
            que.pop();
            for(int i = head[root]; i != -1; i = next[i])
            {   //边还有残余容量,且下一个点还没分层
                if(level[to[i]] == -1 && cap[i])
                {
                    level[to[i]] = level[root] + 1;
                    if(to[i] == n_point)
                        return true;
                    que.push(to[i]);
                }
            }
        }
        return false;
    }
    
    int dfs(int root, int f, int n_point)
    {
        if(root == n_point)
            return f;
        int flow, ans = 0;
        for(int i = head[root]; i != -1; i = next[i])
        {
            int m = min(cap[i], f - ans);
            if(cap[i] && level[root]+1 == level[to[i]] &&
               (flow = dfs(to[i], m, n_point ) )   )
            {   //下标从0开始,则正向边为偶数,反向边为基数;
                cap[i] -= flow;
                cap[i^1] += flow;//下标从1开始则不能用  异或
                ans += flow;
            }
        }
        if(ans == 0)    //若没找到增广路,这时注意要把该点
            level[root] = -1;   //的层次标为-1,表示不能到达
        return ans;
    }
    
    void dinic(int n_point)
    {
        int flow = 0;
        while(bfs(1, n_point))  //分层
        {
            while(1)    //每条增广路都有一个瓶颈(增光路上最小容量的边)
            {   //每次分层都要把所有增广路的瓶颈都清除掉,再重新分层
                int f = dfs(1, INF, n_point);//因此最多层分v次
                if(f == 0)
                    break;
                flow += f;
            }
        }
        printf("%d\n", flow);
    }
    
    int main()
    {
        eid = 0;
    
        int n_case;
        scanf("%d", &n_case);
        for(int t = 1; t <= n_case; ++t)
        {
            printf("Case %d: ", t);
            int n_point, n_edge;
            scanf("%d%d", &n_point, &n_edge);
            memset(head, -1, sizeof(head));
            while(n_edge--)
            {
                int from, to, f;
                scanf("%d%d%d", &from, &to, &f);
                add_edge(from, to, f);
            }
            dinic(n_point);
        }
        return 0;
    }
  • 相关阅读:
    @jackychua博客
    c#类与对象
    SQL SERVER 触发器
    .NET平台及C#面向对象编程
    数据库设计指南【转】
    HTTP 协议是一种请求/响应型的协议
    各种字符编码方式详解及由来(ANSI,GB2312,GBK,Big5,UNICODE,UTF8,UTF16)
    常用协议端口 POP3,IMAP,SMTP,Telnet,HTTP,HTTPS
    asp.net Request.Form Request.para Request.Querystring 区别
    Gzipstream 解压问题
  • 原文地址:https://www.cnblogs.com/gabo/p/2623445.html
Copyright © 2011-2022 走看看