/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
Copyright (c) 2011 panyanyany All rights reserved.
URL : http://poj.org/problem?id=1459
Name : 1459 Power Network
Date : Thursday, February 02, 2012
Time Stage : 2 hours
Result:
9765364 panyanyany
1459
Accepted 332K 125MS C++
3831B 2012-02-02 15:54:07
Test Data :
Review :
用dinic算法,时间好像还是有点慢~~~
//----------------------------------------------------------------------------*/
#include <cstdio>
#include <CSTRING>
#define MEM(a, v) memset (a, v, sizeof (a)) // a for address, v for value
#define max(x, y) ((x) > (y) ? (x) : (y))
#define min(x, y) ((x) < (y) ? (x) : (y))
#define INF (0x3f3f3f3f)
#define MAXN (103)
#define MAXE (MAXN*MAXN)
struct EDGE {
int u, v, c, n ;
};
int n, m, eCnt, np, nc ;
int dist[MAXN], vertex[MAXN], q[MAXN] ;
EDGE edge[MAXE] ;
void init()
{
eCnt = 0 ;
MEM(vertex, -1);
MEM(edge, 0);
}
int findEdge (int u, int v)
{
int e ;
for (e = vertex[u] ; e != -1 ; e = edge[e].n)
if (edge[e].v == v)
break ;
return e ;
}
void insert(int u, int v, int c)
{
int e ;
if (-1 == (e = findEdge (u, v)))
{
edge[eCnt].u = u ;
edge[eCnt].v = v ;
edge[eCnt].c += c ;
edge[eCnt].n = vertex[u] ;
vertex[u] = eCnt++ ;
// 顺带加上反向边
edge[eCnt].u = v ;
edge[eCnt].v = u ;
edge[eCnt].c += 0 ;
edge[eCnt].n = vertex[v] ;
vertex[v] = eCnt++ ;
}
else
{
edge[e].c += c ;
edge[e^1].c += 0 ;
}
}
int dinic (const int beg, const int end)
{
// printf ("---beg: %d, end: %d---\n", beg, end) ;
int ans = 0 ;
while (true)
{
int head, tail, u, v, e, i ;
head = tail = 0 ;
MEM(dist, -1);
q[tail++] = beg ;
dist[beg] = 0 ;
// 构建层次图
// printf ("\n构建层次图\n") ;
while (head < tail)
{
// 遍历所有与 v 点直接相连的边
v = q[head++] ;
for (e = vertex[v] ; e != -1 ; e = edge[e].n)
{
// printf ("v:%d e:%d edge: u:%d, v:%d, c:%d, n:%d, dist[%d]:%d + 1 == dist[%d]:%d\n",
// v, e, edge[e].u, edge[e].v, edge[e].c, edge[e].n, v, dist[v], edge[e].v, dist[edge[e].v]) ;
if (edge[e].c > 0 && dist[edge[e].v] == -1)
{
dist[edge[e].v] = dist[v] + 1 ;
q[tail++] = edge[e].v ;
if (end == edge[e].v)
{
head == tail ;
break ;
}
}
}
}
// 层次图不能到达汇点
if (dist[end] == -1)
break ;
tail = 0 ;
v = beg ;
while (true)
{
// 找到一条增广路
if (end == v)
{
int flow, ebreak ;
flow = INF ;
// 找到增广路中能够增加的最大流量 flow
for (i = 0 ; i < tail ; ++i)
{
if (flow > edge[q[i]].c)
{
flow = edge[q[i]].c ;
ebreak = i ;
}
}
ans += flow ;
// 对增广路径中的每条正所边减去 flow,
// 同时反向边加上 flow
for (i = 0 ; i < tail ; ++i)
{
edge[q[i]].c -= flow ;
edge[q[i]^1].c += flow ;
}
// 下一次寻找增广路就从 v 开始
v = edge[q[ebreak]].u ; // 一开始写的 edge[ebreak].u,错到吐……
tail = ebreak ;
}
// 以 v 为增广路径的先头顶点,寻找下一条可增广的边
for (e = vertex[v] ; e != -1 ; e = edge[e].n)
{
if (edge[e].c > 0 && dist[v]+1 == dist[edge[e].v])
break ;
}
// 若找不到可增广的边
if (-1 == e)
{
if (tail == 0) // 增广路径队列中已经没有边了
break ;
// 退一条边
v = edge[q[--tail]].u ;
// 拆边
dist[edge[q[tail]].v] = -1 ;
}
else // 找到一条可增广的边
{
q[tail++] = e ; // 将其加入队列
v = edge[e].v ; // 设置新的先头顶点
}
}
}
return ans ;
}
int main()
{
int i, j;
int u, v, c ;
while (scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF)
{
init() ;
for (i = 0 ; i < m ; ++i)
{
scanf (" (%d,%d)%d", &u, &v, &c);
insert (u+1, v+1, c) ;
}
for (i = 0 ; i < np ; ++i)
{
scanf (" (%d)%d", &u, &c) ;
insert (0, u+1, c) ;
}
for (i = 0 ; i < nc ; ++i)
{
scanf (" (%d)%d", &u, &c) ;
insert (u+1, n+2, c) ;
}
printf ("%d\n", dinic(0, n+2)) ;
}
return 0;
}
分享到:
相关推荐
[Din70]Algorithm for solution of a problem of maximum flow in a network with power estimation.pdf 最大流最高标号法(DINIC法)的论文原文
最大流的Dinic算法,时间复杂度O(EV^2),代码简单而高效
最大流问题在图论和网络优化中占有重要地位,它旨在寻找从源点到汇点在网络中的最大流量,而不会超过任何边的容量限制。在这个问题的求解中,Dinic算法和Shortest Augmenting Path (SAP)算法是两种高效的方法。 ...
【二分图顶点覆盖->最小割->最大流->Dinic算法求解】 解题报告+AC代码 http://hi.csdn.net/!s/WKVPR0 ----> 我的所有POJ解题报告 http://blog.csdn.net/lyy289065406/article/details/6642573
最大网络流问题在图论和运筹学中占有重要地位,它主要研究在一个有向图中,从源点到汇点能通过的最大流量。Dinic算法是由苏联计算机科学家E. A. Dinic于1970年提出的,是一种解决此类问题的有效算法。该算法基于层的...
Dinic于1970年提出的求解最大流问题的有效算法,它的主要特点是基于层的概念和增广路径的思想。下面我们将深入探讨Dinic算法的基本原理和步骤。 1. **初始化**:首先定义源点s和汇点t,将所有边的容量设为边上的...
Dinic算法的基本思路: 1.根据残量网络计算层次图。 2.在层次图中使用DFS进行增广直到不存在增广路 3.重复以上步骤直到无法增广
用DINIC方法实现最大流算法,亲测可以运行!VS2008环境下编辑运行通过!
网络流dinic模板,非本人原创。网络流dinic模板,非本人原创
Dinic算法是一种高效的求解最大流问题的方法,通过构建层次化的残余网络并利用DFS寻找增广路径来不断更新流量,最终找到网络的最大流。通过对算法的深入理解与实践,可以帮助我们在实际问题中更好地应用这一算法。
最大流的 Dinic 算法的 C++ 实现。 以下是操作摘要: FlowNetwork f(n, m) :具有 n 个顶点(0 到 n-1)和 m 个有向边的新网络, f.add(x, y, c) :添加从节点 x 到节点 y 的有向边,容量为 c, f.flow(s, t) :...
本文将详细介绍Dinic算法,这是一种高效的求解网络最大流的算法。 首先,我们要理解什么是最大流。在网络流问题中,我们有一个带权重的有向图,其中每个边代表一个可以传输流量的连接,每条边都有一个容量限制。...
### 非递归邻接表DINIC最大流算法详解 #### 一、引言 在图论中,寻找网络中的最大流量是一项经典问题。其中,DINIC算法(由Yefim Dinitz于1970年提出)是一种高效解决这类问题的方法。本文将详细介绍一个非递归版本...
Dinic于1970年提出,是一种求解网络最大流问题的高效算法。在图论和运筹学中,网络流问题涉及到在一个有向图中从一个源节点到一个汇点传输“流量”,同时满足容量限制和供需平衡的条件。Dinic算法以其优秀的性能和...
最大流模板.cpp dinic
【标题】"POJ2195-Going Home" 是一道来自北京大学在线判题系统POJ的编程题目,主要考察的是运用费用流算法解决实际问题的能力。这道题的中文名称是“回家”,通过题目我们可以推测它可能涉及到路径规划或者资源分配...
给师弟师妹们讲网络流Dinic算法与可行流用到的讲义,感觉还是不错,分享一下~
常见的最大流算法有Ford-Fulkerson方法(包括Dinic算法和Edmonds-Karp算法)、Shortest Augmenting Path(SAP)算法等。这些算法的核心思想是寻找增广路径,即从源点到汇点的路径,其容量未达到最大值,通过反复增加...
Edmonds-Karp算法和Dinic算法是解决这类问题的两种著名算法,它们都用于寻找一个图的最大流。下面将详细讨论这两个算法以及它们在C++中的实现。 首先,让我们了解Edmonds-Karp算法。这个算法基于增广路径的概念,即...