[51nod2953] 土地划分

问题描述

Y国有N座城市,并且有M条双向公路将这些城市连接起来,并且任意两个城市至少有一条路径可以互达。

Y国的国王去世之后,他的两个儿子A和B都想成为新的国王,但他们都想让这个国家更加安定,不会用武力解决问题。

于是他们想将这个国家分成两个小国家A国和B国。现在,A拥有1号城市,B拥有N号城市,其他的城市还尚未确定归属哪边(划分之后的国家内部城市可以不连通)。

由于大家都想让国家变得更好,而某些城市的人民愿意国王的A儿子作为他们的领袖,而某些城市更看好B,而为了交通的便捷,如果划分后的公路连接两个同一个国家的城市,那么更利于城市之间的交流。于是大臣们设计了一种对土地划分的评分机制,具体如下:

\1. 对于城市i,如果它划分给A国,将得到VA[i]的得分;划分给B国,将得到VB[i]的得分。

\2. 对于一条公路i,如果它连接两个A国的城市,将得到EA[i]的得分;连接两个B国的城市,将得到EB[i]的得分;否则,这条公路将失去意义,将扣除EC[i]的得分。

现请你找到最优的土地划分,使得这种它的评分最高。

输入格式

第一行包含两个整数N,M,含义如问题描述所示。

接下来一行N-2个非负整数,表示VA[2..N-1]。

接下来一行N-2个非负整数,表示VB[2..N-1]。

接下来M行,每行五个非负整数描述一条公路:X Y EA[i] EB[i] EC[i],含义如问题描述所示。

输出格式

输出有且仅有一个整数,表示最高评分。

样例输入

3 3

8

9

1 2 2 6 2

2 3 8 5 7

1 3 9 4 1

样例输出

11

数据范围

10% 2 <= N <= 20 2 <= M <= 70

20% 2 <= N <= 20 2 <= M <= 150

50% 2 <= N <= 2000 2 <= M <= 8000

100% 2 <= N <= 10000 2 <= M <= 40000

保证运算过程中及最终结果不超过32位带符号整数类型的表示范围

解析

考虑如何构造最小割模型。关键是割边的意义。

首先,源点向一个点连容量为该点归A国的得分的边,同时这个点向汇点连容量为该点归B国的得分的边。这样就能保证一个点一定只会归属一个国家。特殊的,1号点只有和源点的边,n号点只有和汇点的边,容量均为无穷大。

然后考虑边。一共有三种情况:边的两边都属于A,得到两个属于A的分数加上EA;边的两边都属于B,得到两个属于B的分数加上EB;以及两边各属于一个国家,付出EC的代价。要保证割边的方案只能一一对应这三种情况,对于边\((u,v)\)我们可以这样构造:

即将一条边拆成两个点。最后跑最大流求得最小割即可。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define N 1000002
#define M 1000002
using namespace std;
const int inf=1<<30;
int head[N],ver[M*2],nxt[M*2],cap[M*2],l;
int n,m,s,t,i,dis[N],ans;
int read()
{
	char c=getchar();
	int w=0;
	while(c<‘0‘||c>‘9‘) c=getchar();
	while(c<=‘9‘&&c>=‘0‘){
		w=w*10+c-‘0‘;
		c=getchar();
	}
	return w;
}
void insert(int x,int y,int z)
{
	ver[l]=y;
	cap[l]=z;
	nxt[l]=head[x];
	head[x]=l;
	l++;
	ver[l]=x;
	nxt[l]=head[y];
	head[y]=l;
	l++;
}
bool bfs()
{
	queue<int> q;
	memset(dis,-1,sizeof(dis));
	q.push(s);
	dis[s]=0;
	while(!q.empty()){
		int x=q.front();
		q.pop();
		for(int i=head[x];i!=-1;i=nxt[i]){
			int y=ver[i];
			if(dis[y]==-1&&cap[i]>0){
				dis[y]=dis[x]+1;
				q.push(y);
			}
		}
	}
	return (dis[t]!=-1);
}
int dfs(int x,int flow)
{
	if(x==t||flow==0) return flow;
	int ans=0;
	for(int i=head[x];i!=-1;i=nxt[i]){
		int y=ver[i];
		if(dis[y]==dis[x]+1&&cap[i]>0){
			int a=dfs(y,min(flow,cap[i]));
			flow-=a;
			ans+=a;
			cap[i]-=a;
			cap[i^1]+=a;
		}
		if(flow==0) break;
	}
	if(flow) dis[x]=-1;
	return ans;
}
int main()
{
	memset(head,-1,sizeof(head));
	n=read();m=read();
	t=n+2*m+1;
	for(i=2;i<n;i++){
		int va=read();
		insert(s,i,va);
		ans+=va;
	}
	for(i=2;i<n;i++){
		int vb=read();
		insert(i,t,vb);
		ans+=vb;
	}
	insert(s,1,inf);
	insert(n,t,inf);
	for(i=1;i<=m;i++){
		int u=read(),v=read(),ea=read(),eb=read(),ec=read();
		insert(u,v,ec);insert(v,u,ec);
		insert(s,n+i,ea);insert(n+i,u,inf);insert(n+i,v,inf);
		insert(n+m+i,t,eb);insert(u,n+m+i,inf);insert(v,n+m+i,inf);
		ans+=ea+eb;
	}
	while(bfs()) ans-=dfs(s,inf);
	printf("%d\n",ans);
	return 0;
}

原文地址:https://www.cnblogs.com/LSlzf/p/12663171.html

时间: 2024-10-14 07:08:45

[51nod2953] 土地划分的相关文章

土地划分

现有一块长方形土地,可看成n个小方块组成,这n个小方块依次编号为1-n,现要在这块土地上种A.B两种庄稼,需将该快土地划分成两大块,如果划分结果在第i块和第i+1块之间,则输出{i,i+1},i可以取0或n,这种情况说明有一种庄稼没有种. 专家经过m次鉴定,确定哪个小块适合种那种庄稼,每次鉴定,如果适合种Ai+1庄稼标记为1,适合种B庄稼标记为0,现设计一程序,确定土地划分,使得你划分的土地的小方块和专家鉴定的结果的小方块不一致的个数最少,如果有多解,则取i最大的那个(即右边划分的最少的情况)

fzu 1015 土地划分(判断线段相交+求出交点+找规律)

链接:http://acm.fzu.edu.cn/problem.php?pid=1015  Problem 1015 土地划分 Accept: 714    Submit: 1675Time Limit: 1000 mSec    Memory Limit : 32768 KB  Problem Description 在Dukeswood这块土地上生活着一个富有的农庄主和他的几个孩子.在他临终时,他想把他的土地分给他的孩子.他有许多农场,每个农场都是一块矩形土地.他在农场地图上划上一些直线将

题解 51nod2935 土地划分

题解 51nod2935 土地划分 题面 51nod 解析 一眼最小割考虑怎么建图. 从最简单的边连起:对于每个点 \(i\),连边 \((S,i,A_i)\),\((i,T,B_i)\), (\(S,T\) 分别为源,汇点) 然后考虑每条边 \((x,y)\)的问题, 如果两个点都划分给 \(A\),那在图上就是两个点到 \(T\) 的边都被割掉了, 因此我们新建一个点 \(z\) ,连边 \((x,z,\inf),(y,z,\inf),(z,T,EB_i)\) 即割掉都划分给 \(B\) 的

BZOJ 3511 土地划分

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3511 题目分析: 看上去和前面的人员雇佣以及小M种田都很像. 最小割模型来求最大值,一般都是考虑怎样构图使得满足一个组合能被表示出来,而且当满足一个组合的时候,能产生或失去所需的效益.[割掉的是不要的] 我们将s与1相连,连为INF,这样就不会被割,n向t连边,同理. 因为1和n会有边连接,所以我们才多建出了节点s,t. 然后对于每个点i,s向i连wa[i],i向t连wb[i],这样就满

BZOJ3511 土地划分 题解&amp;代码

pkusc发现自己不会费用流233333于是两天速成费用流[然而这是一道最小割(最大流QwQ 题意: 给出n个点m条边,并设定: 点x在被划分至集合A时获得权值A[x],否则即被划分至集合B并获得权值B[x]: 边(x,y)连接的x和y均属于集合A时获得权值ea,均属于集合B时获得权值eb,否则获得权值-ec. 题解:这题-反正我是没自己建出图来. 对于点x,从S(代表集合A)向x连容量为va的边,从x向T(代表集合B)连容量为vb的边. 对于边(x,y),从S向x和y分别连容量为ea/2的边,

FZU 1015 土地划分

  Description 在Dukeswood这块土地上生活着一个富有的农庄主和他的几个孩子.在他临终时,他想把他的土地分给他的孩子.他有许多农场,每个农场都是一块矩形土地.他在农场地图上划上一些直线将矩形分成若干块.当他划直线时,他总是从矩形边界上的某一点划到另一个矩形边界上的点,这条线的结束点将成为下一条线的起始点.他划线时从不会让任三线共点.例如图1是某一种划分结果. 图1 划分的起始点和结束点均以五角星标记.当他完成划分后,他想要数一下划出的土地的块数以确保每个孩子都有一块地.例如,图

hdu 1241 Oil Deposits

题意:用广度优先搜索 //c++写输入时有问题 1)这个是深搜 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> /* map数组是用来装字符的 n,m提高作用域,使訪问的权限变高 dir方便广度优先搜索,由于要搜索8个方向.这样做最方便 */ char map[101][101]; int n,m; int dir[8][2]={{-1,-1},{0,-

6、快速排序

一.分而治之 分而治之(divide and conquer,DnC)是一种解决问题的思路,它的核心就是利用递归函数,不断把一个问题变成越来越小的问题,直到出现解决条件为止的解题思路. 二.分而治之解题实例 1.问题:假如你是一个农场主,你有一块1680×680的土地,现要求你将土地划分成均匀的方块,且方块的面积尽可能大,现求出最大的方块边长. 分而治之:分而治之解决问题的过程包括两个步骤:①找到最简单的情况(基础条件):②不断缩小问题的规模. 分析:由于原土地是一个矩形,所以最简单的情况是,该

(经典DFS)HDU_1241 Oil Deposits

HDU_1241 Oil Deposits Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land i