poj2391 Ombrophobic Bovines(二分+floyd+最大流)

题意:给定一个有n个顶点和m条边的无向图,点i 处有Ai头牛,点i 处的牛棚能容纳Bi头牛,每条边有一个时间花费ti(表示从一个端点走到另一个端点所需要的时间),求一个最短时间T使得在T时间内所有的牛都能进到某一牛棚里去。(1 <= N <= 200, 1 <= M <= 1500,0 <= Ai <= 1000, 0 <= Bi <= 1000, 1 <= Dij <= 1,000,000,000)

思路:第一次做网络流的小白完全不知道怎么建图....每一个牛棚都可以看作一个汇点,所以构造一个超级汇点,每一个牛棚连一条边到T,容量就是这个牛棚的最大容量,自然也要添加一个超级源点,每一个牛棚到源点也连一条边,容量为当前这个牛棚的牛的数量。这个时候问题来了,比如点1到点2的距离为40,点2到点3的距离为30,我限制走的距离不能超过40的话那么点1到点2,点2到点3都可以走,这样的话其实就相当于点1和点3也间接连起来了而距离为70,会出现错误的结果。所以这个时候就需要拆点来解决,把点i拆成i'和i'',i'和源点连接,i''和汇点连接,如果两个点的距离少于我限制的距离,就将i'和j''连接。为什么这样可以解决这个问题呢?如果是刚才的例子的话就是1'和2''连接,2'和3''连接,这样1'就不会和点3有相连关系了。

            解决了这个问题之后就是用floyd求出两点之间的最短距离,然后二分最短距离看最大流是否等于牛的总数即可

Trick:这题的路径距离很大,注意用LL,另外拆点的话总点数记得比题目要求大两倍以上


#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <set>
#include <ctime>
#include <cmath>
#include <cctype>
using namespace std;
#define maxn 600
#define INF 1e9
#define LLINF 1LL<<60
#define LL long long
int cas=1,T;
struct Edge
{
	int from,to,cap,flow;
	Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
int n,m;
struct Dinic
{
//	int n,m;
    int s,t;
	vector<Edge>edges;        //边数的两倍
	vector<int> G[maxn];      //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
	bool vis[maxn];           //BFS使用
	int d[maxn];              //从起点到i的距离
	int cur[maxn];            //当前弧下标
	void init()
	{
	   for (int i=0;i<=2*n+1;i++)
		   G[i].clear();
	   edges.clear();
	}
	void AddEdge(int from,int to,int cap)
	{
		edges.push_back(Edge(from,to,cap,0));
		edges.push_back(Edge(to,from,0,0));        //反向弧
		int mm=edges.size();
		G[from].push_back(mm-2);
		G[to].push_back(mm-1);
	}
	bool BFS()
	{
		memset(vis,0,sizeof(vis));
		queue<int>q;
		q.push(s);
		d[s]=0;
		vis[s]=1;
		while (!q.empty())
		{
			int x = q.front();q.pop();
			for (int i = 0;i<G[x].size();i++)
			{
				Edge &e = edges[G[x][i]];
				if (!vis[e.to] && e.cap > e.flow)
				{
					vis[e.to]=1;
					d[e.to] = d[x]+1;
					q.push(e.to);
				}
			}
		}
		return vis[t];
	}

	int DFS(int x,int a)
	{
		if (x==t || a==0)
			return a;
		int flow = 0,f;
		for(int &i=cur[x];i<G[x].size();i++)
		{
			Edge &e = edges[G[x][i]];
			if (d[x]+1 == d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0)
			{
				e.flow+=f;
				edges[G[x][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if (a==0)
					break;
			}
		}
		return flow;
	}

	int Maxflow(int s,int t)
	{
		this->s=s;
		this->t=t;
		int flow = 0;
		while (BFS())
		{
			memset(cur,0,sizeof(cur));
			flow+=DFS(s,INF);
		}
		return flow;
	}
}dc;
int can[maxn];
int used[maxn];
LL dis[maxn][maxn];
void floyd()
{
    for (int k = 1;k<=n;k++)
		for (int i = 1;i<=n;i++)
			for (int j = 1;j<=n;j++)
				if (dis[i][k]<LLINF && dis[k][j]<LLINF)
					dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
bool solve(LL limit,int full_flow)
{
	dc.init();
	for (int i = 1;i<=n;i++)
	{
		dc.AddEdge(0,i,used[i]);
		dc.AddEdge(i+n,n*2+1,can[i]);
	}
	for (int i = 1;i<=n;i++)
		for (int j = 1;j<=n;j++)
			if (dis[i][j] <=limit)
				dc.AddEdge(i,j+n,INF);
	return dc.Maxflow(0,n*2+1)==full_flow;
}
int main()
{
	//freopen("in","r",stdin);
	while (scanf("%d%d",&n,&m)!=EOF)
	{
		LL l=0,r=0;
		int sum = 0;
		dc.init();
		for (int i = 1;i<=n;i++)
			for (int j = 1;j<=n;j++)
				dis[i][j]= i==j?0:LLINF;
		for (int i = 1;i<=n;i++)
		{
			scanf("%d%d",&used[i],&can[i]);
			sum+=used[i];
		//	dc.AddEdge(0,i,used[i]);
		//	dc.AddEdge(i+n,n*2+1,can[i]);
		}
		for (int i = 1;i<=m;i++)
		{
			int u,v;
			LL d;
			scanf("%d%d%lld",&u,&v,&d);
			dis[u][v]=dis[v][u]=min(dis[u][v],d);
		}
        floyd();
		for (int i = 1;i<=n;i++)
			for (int j = 1;j<=n;j++)
				if (dis[i][j]!=LLINF)
					r=max(r,dis[i][j]);
        if (!solve(r,sum))                
		{
			printf("-1\n");
            continue;
		}
		else
		{
            while (l<r)
			{
				LL mid = l+(r-l)/2;
				if (solve(mid,sum))
					r=mid;
				else
					l=mid+1;
			}
		}
		printf("%lld\n",r);
	}
	//printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC);
	return 0;
}


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

Hint

OUTPUT DETAILS: 

In 110 time units, two cows from field 1 can get under the shelter in that field, four cows from field 1 can get under the shelter in field 2, and one cow can get to field 3 and join the cows from that field under the shelter in field 3. Although there are other plans that will get all the cows under a shelter, none will do it in fewer than 110 time units.




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值