Drainage Ditches - poj 1273(网络流模板)

题意:1是源点,m是汇点,求出来最大流量,没什么好说的就是练习最大流的模板题

**************************************************************

 

先用Edmonds-Karp的算法做一下试试吧
重边贡献了 1W,要加上所有的重边才算是两点间最大流量

***********************************************************************************************************************

/************************************/
/** 使用Edmonds-Karp 最短增广路算法*/
/** 邻接矩阵实现                   */
/** 2015/8/7/9:39                   */
/************************************/

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;

const int MAXN = 205;
const int oo = 1e9+7;

///1是源点,M是汇点,N条边
int G[MAXN][MAXN], M, N;
int pre[MAXN];///记录每个点的前驱,也就是父节点
bool used[MAXN];

///s代表源点,e代表汇点,可以到达汇返回true,否则返回false
bool BFS(int s, int e)
{
    memset(used, falsesizeof(used));
    queue<int> Q;
    Q.push(s);
    used[s] = true;

    while(Q.size())
    {
        s = Q.front();Q.pop();

        if(s == e) return true;

        for(int i=1; i<=M; i++)
        {
            if(G[s][i] && !used[i])
            {
                pre[i] = s;
                used[i] = true;
                Q.push(i);
            }
        }
    }

    return false;
}
int Karp(int s, int e)
{
    int MaxFlow = 0;

    while( BFS(s, e) == true )
    {///如果有增量
        int MinFlow = oo, v;

        v = e;

        while(v != s)
        {///求出来路径上最小流量
            MinFlow = min(MinFlow, G[pre[v]][v]);
            v = pre[v];
        }

        MaxFlow += MinFlow;
        v = e;

        while(v != s)
        {///边上的所有点减去最小流量,反边增加流量
            G[pre[v]][v] -= MinFlow;
            G[v][pre[v]] += MinFlow;

            v = pre[v];
        }
    }

    return MaxFlow;
}

int main()
{
    while(scanf("%d%d", &N, &M) != EOF)
    {
        int i, u, v, c;

        memset(G, falsesizeof(G));

        for(i=1; i<=N; i++)
        {
            scanf("%d%d%d", &u, &v, &c);
            G[u][v] += c;///有重边,两点间应该算上所有边
        }

        printf("%d\n", Karp(1, M));
    }

    return 0;
}
View Code

 

邻接表实现

***********************************************************************************************************************

/************************************/
/// 使用Edmonds-Karp 最短增广路算法
/// 邻接表实现
/// 2015年8月7日10:13:55
/************************************/

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;

const int MAXN = 205;
const int oo = 1e9+7;

struct Edge{int u, v, Flow, next;}e[MAXN<<1];
int Head[MAXN], cnt;
int pre[MAXN], used[MAXN];

void InIt()
{
    memset(Head, -1sizeof(Head));
    cnt = 0;
}
void AddEdge(int u, int v, int Flow)
{
    e[cnt].u = u;
    e[cnt].v = v;
    e[cnt].Flow = Flow;
    e[cnt].next = Head[u];
    Head[u] = cnt++;
}
bool BFS(int s, int End)
{
    memset(used, falsesizeof(used));
    memset(pre, -1sizeof(pre));
    queue<int> Q;
    Q.push(s);
    used[s] = true;

    while(Q.size())
    {
        s = Q.front();Q.pop();

        if(s == End)return true;

        for(int i=Head[s]; i!=-1; i=e[i].next)
        {
            if(e[i].Flow && used[e[i].v] == false)
            {
                used[e[i].v] = true;
                pre[e[i].v] = i;///记录的是上面的边的位置
                Q.push(e[i].v);
            }
        }
    }

    return false;
}
int Karp(int s, int End)
{
    int MaxFlow = 0;

    while(BFS(s, End) == true)
    {
        int MinFlow = oo, v;

        v = pre[End];

        while(v != -1)
        {
            MinFlow = min(MinFlow, e[v].Flow);
            v = pre[e[v].u];///上个点来的位置
        }

        MaxFlow += MinFlow;
        v = pre[End];

        while(v != -1)
        {
            e[v].Flow -= MinFlow;
            e[v^1].Flow += MinFlow;
            v = pre[e[v].u];
        }
    }

    return MaxFlow;
}

int main()
{
    int N, M;

    while(scanf("%d%d", &N, &M) != EOF)
    {
        int i, u, v, Flow;

        InIt();

        for(i=1; i<=N; i++)
        {
            scanf("%d%d%d", &u, &v, &Flow);
            AddEdge(u, v, Flow);
            AddEdge(v, u, 0);///先添加一条反边的流量是0
        }

        printf("%d\n", Karp(1, M));
    }

    return 0;
}
code

 

Dinic实现 

************************************************************************************************************************

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

const int MAXN = 205;
const int oo = 1e9+7;

struct Edge{int u, v, flow, next;}edge[MAXN*MAXN];
int Head[MAXN], cnt;
int layer[MAXN];///分层
int Start, End;///源点汇点

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 BfsLayer()///使用广搜进行分层
{
    bool used[MAXN]={0};queue<int> Q;
    memset(layer, -1sizeof(layer));
    Q.push(Start);
    used[Start] = true;
    layer[Start] = 0;

    while(Q.size())
    {
        int s = Q.front();Q.pop();

        if(s == End)return true;

        for(int i=Head[s]; i!=-1; i=edge[i].next)
        {
            int v = edge[i].v;

            if(edge[i].flow && !used[v])
            {
                used[v] = true;
                layer[v] = layer[s] + 1;
                Q.push(v);
            }
        }
    }

    return false;
}
int dfs(int u, int MaxFlow)
{///MaxFlow 记录的是这条路径上能经过的最大流量
    if(u == End)return MaxFlow;

    int uFlow = 0;///这个点最多能经过多少流量

    for(int i=Head[u]; i!=-1; i=edge[i].next)
    {
        int v = edge[i].v, flow = edge[i].flow;

        if(layer[v]-1 == layer[u] && flow)
        {
            flow = min(MaxFlow-uFlow, flow);
            flow = dfs(v, flow);

            edge[i].flow -= flow;
            edge[i^1].flow += flow;
            uFlow += flow;
            if(uFlow == MaxFlow)
                break;///已经等于最大流量的时候注意结束
        }
    }

    return uFlow;
}
int Dinic()///用dinic算法求最大流
{
    int MaxFlow = 0;

    while(BfsLayer() == true)
    {
        MaxFlow += dfs(Start, oo);
    }

    return MaxFlow;
}

int main()
{
    int N, M;

    while(scanf("%d%d", &N, &M) != EOF)
    {
        int i, u, v, flow;

        Start = 1, End = M, cnt = 0;
        memset(Head, -1sizeof(Head));

        for(i=1; i<=N; i++)
        {
            scanf("%d%d%d", &u, &v, &flow);
            AddEdge(u, v, flow);
            AddEdge(v, u, 0);
        }

        printf("%d\n", Dinic());
    }

    return 0;
}
View Code

 

SAP实现

*************************************************************************************************************************

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

const int MAXN = 205;
const int oo = 1e9+7;

struct Edge{int u, v, flow, next;}edge[MAXN*MAXN];
int Head[MAXN], cnt;
int Layer[MAXN];///分层
int start, End;///源点汇点
int cur[MAXN], Stack[MAXN],gap[MAXN];
int sumV;///节点的总个数

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++;
}

void BFS()
{
    memset(Layer, -1sizeof(Layer));
    memset(gap, 0sizeof(gap));
    queue<int> Q;
    Q.push(End);
    Layer[End] = 0, gap[0] = 1;

    while(Q.size())
    {
        int u = Q.front();
        Q.pop();

        for(int j=Head[u]; j!=-1; j=edge[j].next)
        {
            int v = edge[j].v;

            if(Layer[v] == -1)
            {
                Layer[v] = Layer[u] + 1;
                gap[Layer[v]]++;
                Q.push(v);
            }
        }
    }
}

int SAP()
{
    int j, top=0, u = start, MaxFlow=0;

    BFS();

    memcpy(cur, Head, sizeof(Head));

    while(Layer[start] < sumV)
    {///源点的层次小于总结点数,汇点是0层

        if(u == End)
        {
            int MinFlow = oo, location;///记录下最小流量边的位置,出栈时候用

            for(j=0; j<top; j++)
            {
                int i = Stack[j];
                if(MinFlow > edge[i].flow)
                {
                    MinFlow = edge[i].flow;
                    location = j;
                }
            }
            for(j=0; j<top; j++)
            {///所有的边减去路径上的最小流量
                int i = Stack[j];

                edge[i].flow -= MinFlow;
                edge[i^1].flow += MinFlow;
            }

            MaxFlow += MinFlow;
            top = location;///退栈
            u = edge[Stack[top]].u;
        }
        else if(gap[Layer[u]-1] == 0)
            break;///u所在的层下面的层没有了,出现了断层,也就没有了可行弧

        for(j=cur[u]; j!=-1; j=edge[j].next)
        {///如果u有可行弧就停止
            if(Layer[u]==Layer[edge[j].v]+1 && edge[j].flow)
                break;
        }

        if(j != -1)
        {///找到了可行弧
            cur[u] = j;///u点的可行弧是j
            Stack[top++] = j;///记录下这条边
            u = edge[j].v;
        }
        else
        {///没有找到可行弧,修改标号
            int MinIndex = sumV;

            for(j=Head[u]; j!=-1; j=edge[j].next)
            {///查找与u相连的最小的层是多少
                if(edge[j].flow && MinIndex > Layer[edge[j].v])
                {///记录下这条可行弧,下次可以直接访问这条边
                    MinIndex = Layer[edge[j].v];
                    cur[u] = j;
                }
            }

            gap[Layer[u]] -= 1;///u改变层,所以u原来所在层的点数减去1
            Layer[u] = MinIndex + 1;
            gap[Layer[u]] += 1;

            if(u != start)
            {///返回上一层
                u = edge[Stack[--top]].u;
            }
        }
    }

    return MaxFlow;
}

int main()
{
    int N, M;

    while(scanf("%d%d", &N, &M) != EOF)
    {
        int i, u, v, flow;
        sumV = M;
        start = 1, End = M, cnt = 0;
        memset(Head, -1sizeof(Head));

        for(i=1; i<=N; i++)
        {
            scanf("%d%d%d", &u, &v, &flow);
            AddEdge(u, v, flow);
            AddEdge(v, u, 0);
        }

        printf("%d\n", SAP());
    }

    return 0;
}
View Code

转载于:https://www.cnblogs.com/liuxin13/p/4709956.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux RTC 驱动模型分析

linux RTC 驱动模型分析RTC(real time clock)实时时钟&#xff0c;主要作用是给Linux系统提供时间。RTC因为是电池供电的&#xff0c;所以掉电后时间不丢失。Linux内核把RTC用作“离线”的时间与日期维护器。当Linux内核启动时&#xff0c;它从RTC中读取时间与日期&#xff0c;…

Install Docker Mac OS X

检查 Mac OS version 要求必须是 OS X 10.6 Snow Leopard or newer to run Boot2Docker安装 Boot2Docker 列表内容下载地址&#xff1a;https://github.com/boot2docker/osx-installer/releases/download/v1.7.0/Boot2Docker-1.7.0.pkg 下载后点击安装&#xff0c;就是按照提示…

linq to sql报错,

以上是由于我把关联表中的string类型写成int类型所导致的&#xff0c;记一下&#xff0c;备用。转载于:https://www.cnblogs.com/server126/archive/2011/05/25/2057416.html

[VC6] RadioBox使用入门

基于对话框的应用程序&#xff0c;界面如下&#xff1a; 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。 具体请参考代码&#xff1a; 关键代码&#xff1a; // del2Dlg.cpp : implementation file //#include "stdaf…

树莓派使用STEP1:装系统

1、windows安装SD卡格式化软件&#xff1a;SDFormatter.exe 2、windows安装系统烧录软件Win32DiskImager.exe 3、下载镜像&#xff1a;https://www.raspberrypi.org/downloads/raspbian/ 并解压缩 4、用Win32DiskImager将下载的镜像文件烧录进SD卡。 5、插上SD到树莓派&…

树莓派使用STEP2:设置网络

安装好系统并开机&#xff0c;插入鼠标键盘和显示器&#xff0c;登陆系统&#xff0c;打开终端。按以下操作。 1、sudo raspi-config 进入配置&#xff0c;打开SSH功能。 Interfacing Options -> SSH 2、扩展系统内存。 Advanced options -> Expand Filesystem 3、设置…

linux3.0-内核自带led驱动移植

********************************************************************************************************************************************************************************** cpu : s3c2440(arm9) linux内核&#xff1a;linux-3.0 开发板 &am…

树莓派使用STEP3:更换镜像源

更换国内镜像源&#xff0c;这里使用中科大的源&#xff0c;软件下载和更新速度更快。 1、sudo nano /etc/apt/sources.list 2、sudo nano /etc/apt/sources.list.d/raspi.list 3、sudo apt-get update && apt-get upgrade

树莓派使用STEP4:安装vim

系统原装的vi操作对新手和学习者不友好&#xff0c;可以用nano编辑器&#xff0c;因为我比较熟悉vi和vim&#xff0c;这里推荐使用vim。首先需要删除原装的vi&#xff0c;然后重新安装新的vim&#xff0c;过程比较简单。 1、卸载预装的vi sudo apt-get remove vim-common 2、…

手机测试pc端网页

在这个问题上徘徊了 一个钟头了&#xff0c;终于被我找到方法了&#xff0c;就赶紧记下来&#xff0c;以后好查阅&#xff01;&#xff01; 主要问题在防火墙&#xff0c;防火墙阻当了80端口&#xff0c;所以怎么用手机访问都是访问不了的。把防火墙关闭就好了&#xff01; 贴上…

树莓派使用STEP5:安装samba文件共享服务器

samba服务器可以在多平台多操作系统搭建文件服务器&#xff0c;用于共享文件。为了方便windows和树莓派交换文件&#xff0c;将samba服务器的搭建过程记录如下。 1、安装samba服务器。 sudo apt-get install samba samba-common-bin 出现以下提示&#xff1a;Modify smb.conf…

ETH—Lwip以太网通信

第39章 ETH—Lwip以太网通信 全套200集视频教程和1000页PDF教程请到秉火论坛下载&#xff1a;www.firebbs.cn 野火视频教程优酷观看网址&#xff1a;http://i.youku.com/firege 互联网技术对人类社会的影响不言而喻。当今大部分电子设备都能以不同的方式接入互联网(Inter…

计算从A地出发到各个地方的路径及距离

数据库环境&#xff1a;SQL SERVER 2005 如题&#xff0c;现有bus表数据如下&#xff0c;dstart是起点&#xff0c;dend是终点&#xff0c;distance是两地的距离。 求从A地出发到各个地方的距离。 有经验的人一看&#xff0c;就知道题目关于树形查询的。SQL SERVER 2005数据库…

树莓派使用STEP6:安装git

git用于创建和管理代码仓&#xff0c;是一个很优秀的版本控制工具。linux/树莓派安装非常简单。 1、sudo apt-get install git-core

cJSON 使用笔记

缘 起 最近在stm32f103上做一个智能家居的项目&#xff0c;其中选择的实时操作系统是 rt_thread OS v1.2.2稳定版本&#xff0c;其中涉及到C和java(android)端数据…

使用虚拟路径时出现404问题

今天在做一个小项目的时候使用了如下路径 web.xml如下&#xff1a; 一切配置都正确&#xff0c;可还是404 在折腾了半天之后发现浏览器的地址栏没有项目名&#xff01;也就是说连接到项目外面去了&#xff0c;果断404。然后才记得虚拟路径前面的“/”和通常用的“../”具有同样…

树莓派使用STEP7:安装wiringPi硬件外设驱动C库

基于C/C开发树莓派外设&#xff0c;比较好的一种库是wiringPi&#xff0c;这里记录安装的流程和步骤。 一、在线安装 1、控制命令行 &#xff1a;git clone git://git.drogon.net/wiringPi 克隆git代码仓库 2、控制命令行&#xff1a; git pull origin 拉取最新的wiringPi…

STM32的I2C主从机通信

最近一段时间在做I2C通信协议&#xff0c;需要在两块STM32之间做I2C通信&#xff0c;定的是主机用IO口模拟&#xff0c;从机用的是STM32的硬件I2C&#xff0c;我的项目要求是需要主从机之间能够进行一串数据收发而不出错&#xff0c;实验时在主机方面&#xff0c;利用IO口模拟主…

css垂直居中那点事

这是我技术博客生涯的第一篇文章&#xff0c;想想还是有点小鸡冻。。。菜鸟的征程现在要开始了 学习css的时候经常被各种问题纠结到不要不要的&#xff0c;没办法&#xff0c;只能写写博客帮助整理一下自己的思绪和帮助一下和我遇到同样问题的小伙伴们 不知道各位学习css的小伙…

Windows常用shell命令大全

From: http://blog.csdn.net/yunzhongfeiniao/article/details/6564577 基于鼠标操作的后果就是OS界面外观发生改变&#xff0c;就得多花学习成本。更主要的是基于界面引导Path与命令行直达速度是难以比拟的。另外Geek很大一部分是键盘控&#xff0c;而非鼠标流的。 整理Wind…