2007: [Noi2010]海拔

Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 2742  Solved: 1318
[Submit][Status][Discuss]

Description

YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域。简单起见,可以将YT市看作一个
正方形,每一个区域也可看作一个正方形。从而,YT城市中包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路
(简称道路),每条双向道路连接主干道上两个相邻的交叉路口。下图为一张YT市的地图(n = 2),城市被划分为2
×2个区域,包括3×3个交叉路口和12条双向道路。 小Z作为该市的市长,他根据统计信息得到了每天上班高峰期
间YT市每条道路两个方向的人流量,即在高峰期间沿着该方向通过这条道路的人数。每一个交叉路口都有不同的海
拔高度值,YT市市民认为爬坡是一件非常累的事情,每向上爬h的高度,就需要消耗h的体力。如果是下坡的话,则
不需要耗费体力。因此如果一段道路的终点海拔减去起点海拔的值为h(注意h可能是负数),那么一个人经过这段路
所消耗的体力是max{0, h}(这里max{a, b}表示取a, b两个值中的较大值)。 小Z还测量得到这个城市西北角的交
叉路口海拔为0,东南角的交叉路口海拔为1(如上图所示),但其它交叉路口的海拔高度都无法得知。小Z想知道在
最理想的情况下(即你可以任意假设其他路口的海拔高度),每天上班高峰期间所有人爬坡所消耗的总体力和的最
小值。

Input

第一行包含一个整数n,含义如上文所示。接下来4n(n + 1)行,每行包含一个非负整数分别表示每一条道路每一个
方向的人流量信息。输入顺序:n(n + 1)个数表示所有从西到东方向的人流量,然后n(n + 1)个数表示所有从北到
南方向的人流量,n(n + 1)个数表示所有从东到西方向的人流量,最后是n(n + 1)个数表示所有从南到北方向的人
流量。对于每一个方向,输入顺序按照起点由北向南,若南北方向相同时由西到东的顺序给出(参见样例输入)。

Output

仅包含一个数,表示在最理想情况下每天上班高峰期间所有人爬坡所消耗的总体力和(即总体力和的最小值),结
果四舍五入到整数。

Sample Input

1
1
2
3
4
5
6
7
8

Sample Output

3

【样例说明】
样例数据见下图。

最理想情况下所有点的海拔如上图所示。
对于100%的数据:1 ≤ n ≤ 500,0 ≤ 流量 ≤ 1,000,000且所有流量均为整数。

 
题解:

显然我们只需要考虑0和1的分界线在何处即可。当然我们需要找到一些边集,把图分成两半,且权值和最小。这不就是最小割吗...所以直接把原图转成对偶图,然后跑dijkstra。

  注意连边的时候考虑方向,我们不妨假定对偶图边经过的方向,左边海拔为0,右边海拔为1,然后只要算0到1的,所以就是正方向的权值。所以我们只需要把方向相反的两条边在对偶图中也构出方向相反的即可。

这样就可以了。

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#define N 507
using namespace std; int n;
int mp[N][N][];
int dis[N][N]; struct dist
{
int x,y,dis;
bool operator < (const dist b) const
{
return dis>b.dis;
}
};
priority_queue<dist>q;
int ans=1e9+;
void insert(int x,int y,int d)
{
if(d<dis[x][y])
{
dis[x][y]=d;
q.push((dist){x,y,d});
}
if(y==)ans=min(ans,d+mp[x][y][]);
if(x==n)ans=min(ans,d+mp[x+][y][]);
}
void Dij()
{
int i,j;
for(i=;i<=n;i++)
insert(,i,mp[][i][]);
for(j=;j<=n;j++)
insert(j,n,mp[j][n+][]);
while(!q.empty())
{
dist now=q.top();q.pop();
if(now.dis>dis[now.x][now.y])continue;
int x=now.x,y=now.y;
if(x>) insert(x-,y,now.dis+mp[now.x][now.y][]);
if(y>) insert(x,y-,now.dis+mp[now.x][now.y][]);
if(x<n) insert(x+,y,now.dis+mp[now.x+][now.y][]);
if(y<n) insert(x,y+,now.dis+mp[now.x][now.y+][]);
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n+;i++)
for(int j=;j<=n;j++)
scanf("%d",&mp[i][j][]);//从西到东
for(int i=;i<=n;i++)
for(int j=;j<=n+;j++)
scanf("%d",&mp[i][j][]);//从北到南
for(int i=;i<=n+;i++)
for(int j=;j<=n;j++)
scanf("%d",&mp[i][j][]);//从东到西
for(int i=;i<=n;i++)
for(int j=;j<=n+;j++)
scanf("%d",&mp[i][j][]);//从南到北
memset(dis,0x3f,sizeof dis);
Dij();
cout<<ans<<endl;
}

Bzoj2007 [Noi2010]海拔(平面图最短路)的更多相关文章

  1. [BZOJ2007][NOI2010]海拔(对偶图最短路)

    首先确定所有点的海拔非0即1,问题转化成裸的平面图最小割问题,进而转化成对偶图最短路(同BZOJ1002). 这题的边是有向的,所以所有边顺时针旋转90度即可. 如下图(S和T的位置是反的). #in ...

  2. BZOJ2007 NOI2010 海拔 平面图转对偶图 最小割

    题面太长啦,请诸位自行品尝—>海拔 分析: 这是我见过算法比较明显的最小割题目了,很明显对于某一条简单路径,海拔只会有一次变换. 而且我们要最终使变换海拔的边权值和最小. 我们发现变换海拔相当于 ...

  3. bzoj2007/luoguP2046 海拔(平面图最小割转对偶图最短路)

    bzoj2007/luoguP2046 海拔(平面图最小割转对偶图最短路) 题目描述: bzoj  luogu 题解时间: 首先考虑海拔待定点的$h$都应该是多少 很明显它们都是$0$或$1$,并且所 ...

  4. 【BZOJ2007】[Noi2010]海拔 对偶图最短路

    [BZOJ2007][Noi2010]海拔 Description YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作 一个正方形,每一个区域也可看 ...

  5. BZOJ2007 [Noi2010]海拔 【平面图最小割转对偶图最短路】

    题目链接 BZOJ2007 题解 这是裸题啊,,要是考试真的遇到就好了 明显是最小割,而且是有来回两个方向 那么原图所有向右的边转为对偶图向下的边 向左的边转为向上 向下转为向左 向上转为向右 然后跑 ...

  6. Luogu2046 NOI2010 海拔 平面图、最小割、最短路

    传送门 首先一个不知道怎么证的结论:任意点的\(H\)只会是\(0\)或\(1\) 那么可以发现原题的本质就是一个最小割,左上角为\(S\),右下角为\(T\),被割开的两个部分就是\(H=0\)与\ ...

  7. P2046 [NOI2010]海拔 平面图转对偶图(最小割-》最短路)

    $ \color{#0066ff}{ 题目描述 }$ YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作 一个正方形,每一个区域也可看作一个正方形. ...

  8. bzoj2007 NOI2010 海拔(对偶图)

    80分(最小割)思路 先考虑如果没有题目中东南角为\(1\)那个限制的话会怎样. 那么只要让每个点的海拔都是\(0\)就行了.这样不论怎样走,最后的答案都是0. 然后再考虑那个东南角为\(1\)的限制 ...

  9. Bzoj2007 [Noi2010]海拔

    Time Limit: 20 Sec  Memory Limit: 552 MB Submit: 2380  Solved: 1130 Description YT市是一个规划良好的城市,城市被东西向 ...

随机推荐

  1. MySQL 导出一句话

    听说是很老的东西了,学习的时候发现还是很好用的,故学习转载过来,留备学习. mysql 导出一句话 方法1:网上流行的方法 流程:(1)建表--->(2)插入数据--->(3)select ...

  2. 洛谷 P2984 [USACO10FEB]给巧克力Chocolate Giving

    题目描述 Farmer John is distributing chocolates at the barn for Valentine's day, and B (1 <= B <= ...

  3. C++实现动态数组

    实现一个动态数组,要求对于随机访问可以在常数时间完成,可以通过push_back向数据的尾部追加元素,可以通过pop_back删除尾部元素,能够满足常见的数组操作. LINE 2016年春招笔试   ...

  4. URAL 1776 Anniversary Firework (概率,区间DP)

    坑,一开始以为,分成两半的时候去最大那个就行了, 实际上这样是不对的,因为有可能出现小的一半的时间比大的要长, 因为还和等待次数有关,且转移的时候需要用到次数更小的状态, 所以状态定义为二维,dp[i ...

  5. Scala 的list

    9.1 使用列表 列表类型:跟数组一样,列表也是同质化的(homogeneous).即所有元素都要是同种类型. 列表结构:所有列表由两部分组成:Nil 和 ::(cons). 基本操作:主要有三个:h ...

  6. js 判断是什么浏览器、是否为谷歌浏览器

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http ...

  7. JS中的delete操作符

    首先,delete删除成功返回true,失败返回false. js代码: function wxCount ($element) { this.init($element); } wxCount.pr ...

  8. Philipp Wagner

    本文大部分来自OpenCV官网上的Face Reconition with OpenCV这节内容(http://docs.opencv.org/modules/contrib/doc/facerec/ ...

  9. CS193p Lecture 4 - Foundation, Attributed Strings

    消息机制 调用一个实例(instance)的方法(method),就是向该实例的指针发送消息(message),实例收到消息后,从自身的实现(implementation)中寻找响应这条消息的方法. ...

  10. 使用CSS来制作类似「黑幕」的效果

    网上几乎没有看到这类的代码,留个档 .heimu,.heimu a{ background-color: #252525; color:#252525; text-shadow: none; }::s ...