`

【最大流+dinic】北大 poj 1459 Power Network

阅读更多

 

/* 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;
}
 
0
0
分享到:
评论

相关推荐

    最大流Dinic算法(最高标号法)原论文

    [Din70]Algorithm for solution of a problem of maximum flow in a network with power estimation.pdf 最大流最高标号法(DINIC法)的论文原文

    网络流最大流Dinic算法代码

    最大流的Dinic算法,时间复杂度O(EV^2),代码简单而高效

    最大流的Dinic算法与SAP算法的实现

    最大流问题在图论和网络优化中占有重要地位,它旨在寻找从源点到汇点在网络中的最大流量,而不会超过任何边的容量限制。在这个问题的求解中,Dinic算法和Shortest Augmenting Path (SAP)算法是两种高效的方法。 ...

    POJ3308-Paratroopers 【Dinic算法求最大流】

    【二分图顶点覆盖-&gt;最小割-&gt;最大流-&gt;Dinic算法求解】 解题报告+AC代码 http://hi.csdn.net/!s/WKVPR0 ----&gt; 我的所有POJ解题报告 http://blog.csdn.net/lyy289065406/article/details/6642573

    最大网络流Dinic算法

    最大网络流问题在图论和运筹学中占有重要地位,它主要研究在一个有向图中,从源点到汇点能通过的最大流量。Dinic算法是由苏联计算机科学家E. A. Dinic于1970年提出的,是一种解决此类问题的有效算法。该算法基于层的...

    图论- 网络流- 最大流- Dinic 算法.rar

    Dinic于1970年提出的求解最大流问题的有效算法,它的主要特点是基于层的概念和增广路径的思想。下面我们将深入探讨Dinic算法的基本原理和步骤。 1. **初始化**:首先定义源点s和汇点t,将所有边的容量设为边上的...

    最大流dinic算法

    Dinic算法的基本思路: 1.根据残量网络计算层次图。 2.在层次图中使用DFS进行增广直到不存在增广路 3.重复以上步骤直到无法增广

    DINIC最大流算法

    用DINIC方法实现最大流算法,亲测可以运行!VS2008环境下编辑运行通过!

    网络流dinic模板

    网络流dinic模板,非本人原创。网络流dinic模板,非本人原创

    网络流Dinic

    Dinic算法是一种高效的求解最大流问题的方法,通过构建层次化的残余网络并利用DFS寻找增广路径来不断更新流量,最终找到网络的最大流。通过对算法的深入理解与实践,可以帮助我们在实际问题中更好地应用这一算法。

    network-flow:最大流的 Dinic 算法的 C++ 实现

    最大流的 Dinic 算法的 C++ 实现。 以下是操作摘要: FlowNetwork f(n, m) :具有 n 个顶点(0 到 n-1)和 m 个有向边的新网络, f.add(x, y, c) :添加从节点 x 到节点 y 的有向边,容量为 c, f.flow(s, t) :...

    Dinic.rar_Dinif2.m_dinic_最大流_最大流算法_最大网络流

    本文将详细介绍Dinic算法,这是一种高效的求解网络最大流的算法。 首先,我们要理解什么是最大流。在网络流问题中,我们有一个带权重的有向图,其中每个边代表一个可以传输流量的连接,每条边都有一个容量限制。...

    非递归邻接表DINIC最大流模板

    ### 非递归邻接表DINIC最大流算法详解 #### 一、引言 在图论中,寻找网络中的最大流量是一项经典问题。其中,DINIC算法(由Yefim Dinitz于1970年提出)是一种高效解决这类问题的方法。本文将详细介绍一个非递归版本...

    dinic网络流算法

    Dinic于1970年提出,是一种求解网络最大流问题的高效算法。在图论和运筹学中,网络流问题涉及到在一个有向图中从一个源节点到一个汇点传输“流量”,同时满足容量限制和供需平衡的条件。Dinic算法以其优秀的性能和...

    最大流模板.cpp dinic

    最大流模板.cpp dinic

    POJ2195-Going Home【费用流】

    【标题】"POJ2195-Going Home" 是一道来自北京大学在线判题系统POJ的编程题目,主要考察的是运用费用流算法解决实际问题的能力。这道题的中文名称是“回家”,通过题目我们可以推测它可能涉及到路径规划或者资源分配...

    最大流DInic算法(链式前向星)

    给师弟师妹们讲网络流Dinic算法与可行流用到的讲义,感觉还是不错,分享一下~

    最大流题解1

    常见的最大流算法有Ford-Fulkerson方法(包括Dinic算法和Edmonds-Karp算法)、Shortest Augmenting Path(SAP)算法等。这些算法的核心思想是寻找增广路径,即从源点到汇点的路径,其容量未达到最大值,通过反复增加...

    edmonds和dinic算法c++比较

    Edmonds-Karp算法和Dinic算法是解决这类问题的两种著名算法,它们都用于寻找一个图的最大流。下面将详细讨论这两个算法以及它们在C++中的实现。 首先,让我们了解Edmonds-Karp算法。这个算法基于增广路径的概念,即...

Global site tag (gtag.js) - Google Analytics