Bzoj 2115
Bzoj 2964

Bzoj 2007

coc youyl posted @ 2015年6月22日 22:51 in bzoj , 423 阅读

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2007

题目分类:网络流,最小割

题意:

给出一个网格图,一个角的海拔是1,对角的海拔是0,给出每条边上各个方向上的人流量,如果是下坡不消耗,是上坡消耗人流量和高度差的积的代价,让你给每个点安排海拔,求最优方案下总消耗。

题解:

考虑单独的一条路径,发现当海拔差集中在一段上一定是最优的,即【0,0,……,0,1,1,……,1,1】

问题转化为求网格图的最小割。

因为数据范围十分大,需要转换成对偶图用最短路来解。

程序:

#include<cstdio>
#include<queue>
using namespace std;
int dis[260000];
struct node
{
	int to,next,va;
}g[1200000];
int n,x1;
int ed,st[260000],inq[260000],S,T;
inline void add(int x,int y,int z)
{
	ed++;
	g[ed].to=y;
	g[ed].va=z;
	g[ed].next=st[x];
	st[x]=ed;
}
inline void spfa()
{
	queue<int>q;
	q.push(S);
	for (int i=S;i<=T;i++)
	{
		dis[i]=2100000000;
		inq[i]=0;
	}
	inq[S]=1;
	dis[S]=0;
	while (!q.empty())
	{
		x1=q.front();
		q.pop();
		inq[x1]=0;
		for (int i=st[x1];i!=0;i=g[i].next)
		{
			if(dis[g[i].to]>dis[x1]+g[i].va)
			{
				dis[g[i].to]=dis[x1]+g[i].va;
				if(inq[g[i].to]==0)
				{
					q.push(g[i].to);
					inq[g[i].to]=1;
				}
			}
		}
	}
}
int main()
{
	scanf("%d",&n);
	S=0;
	T=n*n+1;
	for (int i=0;i<=n;i++)
	{
		for (int j=1;j<=n;j++)
		{
			scanf("%d",&x1);
			if(i==0)add(i*n+j,T,x1);
			else if(i==n)add(S,i*n-n+j,x1);
			else add(i*n+j,i*n-n+j,x1);
		}
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=0;j<=n;j++)
		{
			scanf("%d",&x1);
			if(j==0)add(S,i*n-n+1,x1);
			else if(j==n)add(i*n-n+j,T,x1);
			else add(i*n-n+j,i*n-n+j+1,x1);
		}
	}
	for (int i=0;i<=n;i++)
	{
		for (int j=1;j<=n;j++)
		{
			scanf("%d",&x1);
			if(i==0)add(T,i*n+j,x1);
			else if(i==n)add(i*n-n+j,S,x1);
			else add(i*n-n+j,i*n+j,x1);
		}
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=0;j<=n;j++)
		{
			scanf("%d",&x1);
			if(j==0)add(i*n-n+1,S,x1);
			else if(j==n)add(T,i*n-n+j,x1);
			else add(i*n-n+j+1,i*n-n+j,x1);
		}
	}
	spfa();
	printf("%d\n",dis[T]);
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter