`

【最大流+floyd+二分+dinic】北大 poj 2112 Optimal Milking

阅读更多
/* THE PROGRAM IS MADE BY PYY */
/*----------------------------------------------------------------------------//
    Copyright (c) 2012 panyanyany All rights reserved.

    URL   : http://poj.org/problem?id=2112
    Name  : 2112 Optimal Milking

    Date  : Friday, February 10, 2012
    Time Stage : 4 hours

    Result:                                                                                  9791440	panyanyany
2112
Accepted	592K	172MS	C++
4274B	2012-02-10 15:28:44

Test Data :
2 3 2
0 3 2 1 1
3 0 3 2 0
2 3 0 1 0
1 2 1 0 2
1 0 0 2 0

1 1 1
0 1
1 0
  
2 2 1
0 0 1 3
0 0 2 100
1 2 0 0
3 100 0 0

Review :
犯了一些概念性的错误,太失败了……
//----------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>


#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	(234)

#define DB	/##/

int		K, C, M, n, low, hig ;
int		map[MAXN][MAXN], net[MAXN][MAXN], level[MAXN], q[MAXN] ;

void floyd()
{
	int i, j, k ;

	for (k = 1 ; k <= n ; ++k)
		for (i = 1 ; i <= n ; ++i)
			for (j = i+1 ; j <= n ; ++j)
			{
				map[j][i] = map[i][j] = min(map[i][j], map[i][k]+map[k][j]) ;
			}
}

int dinic (const int beg, const int end)
{
	int sum, i, u, v, head, tail ;
	sum = 0 ;

	while (true)
	{
		head = tail = 0 ;
		q[tail++] = beg ;
		MEM (level, -1) ;
		level[beg] = 0 ;

		while (head < tail)
		{
			u = q[head++] ;
			for (i = beg ; i <= end ; ++i)
				if (net[u][i] > 0 && level[i] == -1)
				{
					level[i] = level[u] + 1 ;
					if (end == i)
					{
						head = tail ;
						break ;
					}
					q[tail++] = i ;
				}
		}
		
		if (-1 == level[end])
			break ;

		tail = 0 ;
		q[tail++] = beg ;
		u = beg ;
		while (1)
		{
			if (end == u)
			{
				int flow = INF, qbreak ;
				for (i = 1 ; i < tail ; ++i)
				{
					u = q[i-1] ;
					v = q[i] ;
					if (flow >= net[u][v])
					{
						flow = net[u][v] ;
						qbreak = i - 1 ;
					}
				}
				sum += flow ;
				for (i = 1 ; i < tail ; ++i)
				{
					u = q[i-1] ;
					v = q[i] ;
					net[u][v] -= flow ;
					net[v][u] += flow ;
				}

				u = q[qbreak] ;
				tail = qbreak + 1 ;
			}

			for (i = beg ; i <= end ; ++i)
				if (net[u][i] > 0 && level[u]+1 == level[i])
					break ;

			if (i > end)
			{
				if (tail-1 == 0)
					break ;
				level[q[--tail]] = -1 ;
				u =q[tail-1] ;
			}
			else
			{
				q[tail++] = i ;
				u = i ;
			}
		}
	}
	return sum ;
}

void makegraph(const int lim)
{
	int i, j ;
	MEM(net, 0) ;
	for (i = 1 ; i <= K ; ++i)
		// 错误代码:for (j = 1 ; j <= n ; ++j)
		// 错误代码: for (j = i+1 ; j <= n ; ++j)
		// 首先,流向必须是单向的,map[u][v] 若有流量,则map[v][u]的流量须为0
		// 其次,必须是由挤奶机流向奶牛,或者从奶牛流向挤奶机。
		for (j = K+1 ; j <= n ; ++j)
			net[i][j] = (map[i][j] <= lim) ;//? INF : 0 ;

	// 源点到所有挤奶机的流量为 M
	for (i = 1 ; i <= K ; ++i)
		net[0][i] = M ;
	// 所有奶牛到汇点的流量为 1
	for (i = K+1 ; i <= n ; ++i)
		net[i][n+1] = 1 ;
}

int main()
{
	int i, j ;
	int ans, tmpans ;

	while (scanf ("%d%d%d", &K, &C, &M) != EOF)
	{
		MEM (net, 0) ;
		MEM (map, 0) ;
		n = K+C ;
		for (i = 1 ; i <= n ; ++i)
			for (j = 1 ; j <= n ; ++j)
			{
				scanf("%d", &map[i][j]) ;
				if (0 == map[i][j])
					map[i][j] = INF ;
			}
		// 求任意两点间最短路,为二分高度做准备
		floyd() ;

		for (i = 1 ; i <= K ; ++i)
			net[0][i] = M ;
		for (i = K+1 ; i <= n ; ++i)
			net[i][n+1] = 1 ;

		ans = INF ;	// 保险起见,先初始化一下
		int mid ;
		// 本来是在 floyd 里面对每条路径进行比较的,然后可以缩小[low,hig]的区间
		// 但是这样代码量大了,比较不容易维护,所以在后来查错的时间就挪出来,
		// 直接赋值了
		low = 0 ;
		hig = INF ;
		while (low <= hig)
		{
			mid = (low + hig) / 2 ;
			// 每次限定改变了,就要重新制一次图
			// 本来是可以在 dinic 里面增加一些代码,在制层次图和增广路的时候对
			// 路径检查距离,从而限定它们的距离的。比如:
			// if (map[u][i] <= mid && net[u][i] > 0 && level[i] == -1)
			// 但是这样一来,相当于给本来完好的代码埋下了未知的地雷。
			// 如果哪里漏了对 map[u][i]<=mid 的判断的话,就很难查错了
			makegraph(mid) ;

			tmpans = dinic (0, n+1) ;
			if (tmpans == C)
			{
				ans = mid ;		// 一开始会习惯性地写成 ans = tmpans 。
				hig = mid - 1 ;
			}
			else
				low = mid + 1 ;
		}
		printf ("%d\n", ans) ;
	}
	return 0 ;
}

0
0
分享到:
评论

相关推荐

    MATLAB+Floyd算法程序合集

    floyd算法matlab 利用 MATLAB 实现 Floyd 算法,可对输入的邻接距离矩阵计算图中任意两点间的最短距离矩阵和路由矩阵,且能查询任意两点间的最短距离和路由。 Floyd 算法适用于求解网络中的任意两点间的最短路径:...

    C++语言+Floyd算法+DFS等等算法实现校园导游咨询系统

    本系统采用Dev C++开发平台来进行编写和测试,用到了类、数组、函数,指针、文件的读取存储操作以及DFS算法和所有顶点对的最短路径(Floyd算法)、 图的各种遍历算法等 用无向网表示XX大学的校园景点平面图,图中顶点...

    北大POJ经典结题报告

    《北大POJ经典结题报告》是一份针对北京大学在线编程平台POJ的解题报告,旨在帮助学习者掌握算法和编程技巧,提升解决问题的能力。POJ(Problem Online Judge)是北大的一个在线编程竞赛系统,提供了丰富的算法题目...

    ACM 北大POJ二百多道题目解答

    这个压缩包“ACM 北大POJ二百多道题目解答”显然包含了在这个平台上解决的超过200个问题的代码解答,旨在帮助学习者理解算法,提高编程技能,并通过实践来深化对编程语言的理解。 POJ中的题目涵盖了各种难度和类型...

    POJ2253-Frogger【Floyd】

    标题中的"POJ2253-Frogger【Floyd】"是指北京大学在线编程平台POJ(Problem Set)上的第2253题——“Frogger”,这是一道编程题目,通常涉及到算法和逻辑思维。Floyd在这里指的是弗洛伊德算法,它可能在这道题的解决...

    北大POJ初级题-数据结构:解题报告+AC代码

    北京大学在线判题系统POJ(Problem Online Judge)是许多编程爱好者和学习者锻炼算法技能的平台,特别是对于初学者,它提供了很多基础题目来帮助理解并应用数据结构。本资源包含的是北大POJ初级题目的解题报告以及...

    poj题目分类

    * 哈希表和二分查找等高效查找法:例如 poj3349、poj3274、poj2151、poj1840、poj2002、poj2503。 * 哈夫曼树:例如 poj3253。 * 堆:例如 poj2513。 * trie 树:例如 poj2513。 4. 简单搜索: * 深度优先搜索...

    poj图论题目汇总

    #### 2112 Optimal Milking - 网络流 - **知识点**:网络流算法。 #### 2125 Destroying The Graph - 最小割 - **知识点**:最小割算法,用于找到分割图的最小代价切割。 #### 2135 Farm Tour - 费用流 - **...

    POJ1125-Stockbroker Grapevine【Floyd】

    【标题】"POJ1125-Stockbroker Grapevine【Floyd】"是一个编程竞赛题目,来源于北京大学的在线评测系统POJ(Problem Online Judge)。该题目主要涉及图论算法中的Floyd-Warshall算法。 【描述】"北大POJ1125-...

    POJ2240-Arbitrage【Floyd】

    【标题】"POJ2240-Arbitrage【Floyd】" 是一个编程竞赛题目,来源于北京大学的在线评测系统POJ(Problem Online Judge)。该题目主要涉及到图论中的Floyd-Warshall算法,是一种解决多源最短路径问题的方法。 【描述...

    基于SSM+Floyd物流管理系统+sql数据库(毕设项目).zip

    【资源说明】 该项目代码主要针对计算机、自动化等相关专业的学生从业者下载使用,项目代码都经过严格调试,确保可以运行!放心下载使用。 也可作为期末课程设计、课程大作业、毕业设计等。具有较高的学习借鉴价值!...

    POJ算法题目分类

    * 最大流的增广路算法:最大流的增广路算法是指计算图的最大流的算法,如 poj1459、poj3436。 三、数据结构 数据结构是指解决问题的数据结构,包括串、排序、简单并查集、哈希表和二分查找等高效查找法、哈夫曼...

    poj1005.zip_北大poj1005

    【标题】"poj1005.zip_北大poj1005"指的是北京大学(北大)在线编程竞赛平台(POJ,Problem Set)上的第1005号算法问题的压缩包资源。这个压缩包可能包含了该问题的题目描述、输入输出样例、数据限制以及提交代码的...

    Dijkstra(迪杰斯特拉)+Floyd(弗洛伊德)最短路径算法C++实现

    代码直接就能用,比较简单的算法实现

    北大POJ初级-基本算法

    【北大POJ初级-基本算法】是一系列针对北京大学在线编程平台POJ的初级算法题目解题报告和通过(AC)代码的集合。这个资源对于学习算法基础和提升编程能力非常有帮助,尤其适合初学者。POJ是许多计算机科学与技术专业...

    北京大学poj题目解题代码

    北京大学的POJ题目解题代码集合是一份宝贵的资源,它涵盖了ACM(国际大学生程序设计竞赛)中的许多问题,旨在帮助学生和编程爱好者提升算法理解与编程技能。POJ(Problem Set for Online Judges)是中国最早的在线...

    北大POJ初级-图算法

    【北大POJ初级-图算法】是一系列针对北京大学在线编程平台POJ(Problem Online Judge)上的初级编程题目,重点在于图论算法的应用。这个解题报告集合了多种图算法的实现,帮助学习者掌握如何在实际问题中运用这些...

    ACM常用算法及其相应的练习题.docx

    * 最大流的增广路算法:KM算法 + poj1459, poj3436 三、数据结构 * 串:poj1035, poj3080, poj1936 * 排序:快排、归并排、堆排 + poj2388, poj2299 * 简单并查集的应用 * 哈希表和二分查找等高效查找法 + poj...

    poj各种分类

    在初级阶段的基础上,中级阶段涵盖了更多复杂的数据结构和算法,如差分约束系统、最小费用最大流、双连通分量、强连通分支、最小割模型等,以及线段树、树状数组、RMQ查询等高级数据结构的应用。这些内容进一步深化...

Global site tag (gtag.js) - Google Analytics