解题报告 之 POJ2391 Ombrophobic Bovines

解题报告 之 POJ2391 Ombrophobic Bovines

Description

FJ‘s cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They have decided to put a rain siren on the farm to let them know when rain is approaching. They intend to create a rain evacuation
plan so that all the cows can get to shelter before the rain begins. Weather forecasting is not always correct, though. In order to minimize false alarms, they want to sound the siren as late as possible while still giving enough time for all the cows to get
to some shelter.

The farm has F (1 <= F <= 200) fields on which the cows graze. A set of P (1 <= P <= 1500) paths connects them. The paths are wide, so that any number of cows can traverse a path in either direction.

Some of the farm‘s fields have rain shelters under which the cows can shield themselves. These shelters are of limited size, so a single shelter might not be able to hold all the cows. Fields are small compared to the paths and require no time for cows to traverse.

Compute the minimum amount of time before rain starts that the siren must be sounded so that every cow can get to some shelter.

Input

* Line 1: Two space-separated integers: F and P

* Lines 2..F+1: Two space-separated integers that describe a field. The first integer (range: 0..1000) is the number of cows in that field. The second integer (range: 0..1000) is the number of cows the shelter in that field can hold. Line i+1 describes field
i.

* Lines F+2..F+P+1: Three space-separated integers that describe a path. The first and second integers (both range 1..F) tell the fields connected by the path. The third integer (range: 1..1,000,000,000) is how long any cow takes to traverse it.

Output

* Line 1: The minimum amount of time required for all cows to get under a shelter, presuming they plan their routes optimally. If it not possible for the all the cows to get under a shelter, output "-1".

Sample Input

3 4
7 2
0 4
2 6
1 2 40
3 2 70
2 3 90
1 3 120

Sample Output

110

题目大意:有n个棚,有m条路,每个棚紧挨着一些牛,每个棚有一定容量。每条路有一个长度,每条路可以同时跑无数条牛。问要让所有牛有棚住,牛中移动距离的最长路最小能有多小?

分析:与前面的题类似,先跑Floyd,然后都是二分,然后跑最大流,直到满足为止。但是这个题建图有一个很困难的地方。就是拆点及拆点的作用。这里把每个棚拆成两个点,负载为INF,关键在于如果两个点u->v可达且路径长度<=mid,那么此时在u的入点连一条边到v的出点。为什么那么奇葩呢,因为转移的量只能转移一次,如果不拆点流量可能转移多次,那么总路径长度将会大于mid。好好体会一下!

另外不知道为什么二分用 while(low<high){ if(...) low=mid+1;else high=mid} 输出low不行,而用ans记录法(见代码)就可以,求大神解答,叩谢!

上代码

<span style="font-size:18px;">#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;

const int MAXN = 510;
const int MAXM = 330110;
const int inf = 0x3f3f3f3f;
const long long INF = 1e16;

struct Edge
{
	int to, cap, next;
};

Edge edge[MAXM];
int level[MAXN];
int head[MAXN];
int cow[MAXN];
int hold[MAXN];
long long dist[MAXN][MAXN];
int src, des, cnt;

void addedge( int from, int to, int cap )
{
	edge[cnt].to = to;
	edge[cnt].cap = cap;
	edge[cnt].next = head[from];
	head[from] = cnt++;

	edge[cnt].to = from;
	edge[cnt].cap = 0;
	edge[cnt].next = head[to];
	head[to] = cnt++;
}

int bfs( )
{
	queue<int> q;
	while (!q.empty( ))
		q.pop( );
	memset( level, -1, sizeof level );
	level[src] = 0;
	q.push( src );

	while (!q.empty( ))
	{
		int u = q.front( );
		q.pop( );
		for (int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].to;

			if (edge[i].cap > 0 && level[v] == -1)
			{
				level[v] = level[u] + 1;
				q.push( v );
			}
		}
	}
	return level[des] != -1;
}

int dfs( int u, int f )
{
	if (u == des)	return f;
	int tem;
	for (int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].to;
		if (edge[i].cap > 0 && level[v] == level[u] + 1)
		{
			tem = dfs( v, min( f, edge[i].cap ) );
			if (tem > 0)
			{
				edge[i].cap -= tem;
				edge[i ^ 1].cap += tem;
				return tem;
			}
		}
	}
	level[u] = -1;
	return 0;
}

int Dinic( )
{
	int ans = 0, tem;

	while (bfs( ))
	{
		while (tem = dfs( src, INF ))
		{
			ans += tem;
		}
	}
	return ans;
}

int main( )
{
	int n, m;
	while (cin >> n >> m)
	{

		int cows = 0;
		memset( dist, -1, sizeof dist );
		src = 0, des = 501;
		for (int i = 1; i <= n; i++)
		{
			scanf( "%d%d", &cow[i], &hold[i] );
			cows += cow[i];
		}

		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
				dist[i][j] = INF;
		}

		for (int i = 1; i <= m; i++)
		{
			int a, b, dis;
			scanf( "%d%d%d", &a, &b, &dis );
			if (dis < dist[a][b])
				dist[a][b] = dist[b][a] = dis;
		}

		//Floyd
		for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		if (dist[i][j] > dist[i][k] + dist[k][j])
		{
			dist[i][j] = dist[i][k] + dist[k][j];
		}

		long long low = -1, high = INF - 1;
		long long ans = -1;
		while (low <= high)
		{
			long long  mid = (low + high) / 2;
			memset( head, -1, sizeof head );
			cnt = 0;
			for (int i = 1; i <= n; i++)
			{
				addedge( src, i, cow[i] );
				addedge( i + 250, des, hold[i] );
				addedge( i, i + 250, hold[i] );
			}

			for (int i = 1; i <= n; i++)
			{
				for (int j = i + 1; j <= n; j++)
				{
					if (dist[i][j] <= mid)
					{
						addedge( i, j + 250, inf );
						addedge( j, i + 250, inf );
					}
				}
			}

			if (Dinic( ) ==cows)
			{
				ans = mid;
				high = mid-1;
			}
			else low = mid+1;
		}
		cout << ans << endl;
	}

	return 0;
}</span>

今天累了,,洗洗睡!

时间: 2024-08-24 14:09:36

解题报告 之 POJ2391 Ombrophobic Bovines的相关文章

POJ2391 Ombrophobic Bovines(网络流)(拆点)

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18205   Accepted: 3960 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h

poj2391 Ombrophobic Bovines

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20459   Accepted: 4403 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h

POJ2391 Ombrophobic Bovines 网络流拆点+二分+floyed

题目链接: id=2391">poj2391 题意: 有n块草地,每块草地上有一定数量的奶牛和一个雨棚,并给出了每一个雨棚的容(牛)量. 有m条路径连接这些草地  ,这些路径是双向的,并且非常宽敞,能够容下无限条牛并排走, 给出经过每条路径所须要消耗的时间 问:全部牛都到达雨棚下的最小时间 解题思路: 类似    牛与挤奶器的问题 http://blog.csdn.net/axuan_k/article/details/45920969  已给出基本思路 与上题最大的差别是: 草地既连接源

POJ2391.Ombrophobic Bovines(不喜欢雨的奶牛)——floyd+二分+拆点+最大流

http://poj.org/problem?id=2391 写的挫的最大流会超时~~~ 题目描述: Jack 农场主的奶牛实在是太讨厌被淋湿了.决定在农场设置降雨警报,这样在快要下 雨的时候可以让奶牛们都知道.他们设置设计了一个下雨撤退计划,这样在下雨之前每头奶牛都 能躲到避雨点.然而,天气预报并不总是准确的.为了使得错误的天气预报影响尽可能小,他们 希望尽可能晚地拉响警报,只要保证留有足够的时间让所有的奶牛都能回到避雨点就可以了. 农场有F 块草地,1≤F≤200,奶牛们在草地上吃草.这些草

poj2391 Ombrophobic Bovines 拆点连边要注意

[题意]:给定F个牛棚和P条路径,每条路径有一个长度,现在每个牛棚有一定的容量和牛数,因为牛棚牛数可能大于容量,所以要牛棚之间的牛要进行相互地移动,每移动一个距离就花费一单位的时间,求从开始移动到每头牛都移动到牛棚的最小时间. 一开始自己建图建错了,把每个点i拆成i'和i'',若i-->j有边 就i''连j'容量INF.再就是源点连每个i‘容量为INF,i’连i''容量为牛数,j'连j''容量为牛棚容量,j''连汇点容量为INF. 但是自己忽略了一点 若1->2->3,这是一条链,而1-

POJ2391:Ombrophobic Bovines

Ombrophobic Bovines Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 21660Accepted: 4658 题目链接:http://poj.org/problem?id=2391 Description: FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes the

poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic

poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 15时39分22秒 * File Name: poj2391.cpp */ #include <ctime> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring&g

POJ 2391 Ombrophobic Bovines (二分,最短路径,网络流sap,dinic,预留推进 )

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14019   Accepted: 3068 Description FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They h

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time