2007: [Noi2010]海拔

Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 2775  Solved: 1331
[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且所有流量均为整数。

80% n,m<=40

这个题的关键之处,就是得出一个结论:每个点要么为1要么为0,感性理解就可以了

然后就成了明显的最小割模型,割出每个点要么为1要么为0,然后就可以过80分了

对于全部数据,可以用对偶图做

考虑到这是一个emmmmmm 规则平面图(?应该是这个名字),可以构建其对偶图,用最短路来求最小割

对偶图

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define mp make_pair
#define fi first
#define se second
#define inf 0x3f3f3f3f
#define ll long long
#define N 260005
using namespace std;
int n,S,T,tot,hd[N],d[N],vis[N];
struct edge{int v,w,next;}e[N*];
void adde(int u,int v,int w){
e[++tot].v=v;
e[tot].w=w;
e[tot].next=hd[u];
hd[u]=tot;
}
char gc(){
static char s[],*p1,*p2;
if(p1==p2)p2=(p1=s)+fread(s,,,stdin);
if(p1==p2)return EOF;
return *p1++;
} void r(int &x){
x=;int f=;char ch=gc();
while(ch>''||ch<''){
if(ch=='-')f=-;
ch=gc();
}
while(ch>=''&&ch<='')x=x*+ch-'',ch=gc();
x*=f;
}
typedef pair<int,int>pii;
priority_queue<pii,vector<pii>,greater<pii> >q;
void dijkstra(){
for(int i=S;i<=T;i++)d[i]=inf;
d[S]=;q.push(mp(d[S],S));
while(!q.empty()){
pii u=q.top();q.pop();
if(vis[u.se])continue;
vis[u.se]=;
for(int i=hd[u.se];i;i=e[i].next){
int v=e[i].v;
if(d[v]<=d[u.se]+e[i].w)continue;
d[v]=d[u.se]+e[i].w;
q.push(mp(d[v],v));
}
}
printf("%d",d[T]);
}
int main(){
#ifdef wsy
freopen("data.in","r",stdin);
#else
freopen("altitude.in","r",stdin);
freopen("altitude.out","w",stdout);
#endif
r(n);
S=;T=n*n+;
int x,s,t; for(int i=;i<=n;i++)
r(x),s=i,t=T,
adde(i,T,x);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
r(x),
s=(i-)*n+j,t=(i-)*n+j,
adde(s,t,x);
for(int i=;i<=n;i++)
r(x),
s=S,t=(n-)*n+i,
adde(S,t,x); for(int i=;i<=n;i++)
for(int j=;j<=n+;j++){
r(x);
if(j==){
s=S;t=(i-)*n+j;
adde(S,t,x);
}
else if(j==n+){
s=i*n;t=T;
adde(i*n,T,x);
}
else{
s=j+(i-)*n-;t=j+(i-)*n;
adde(s,t,x);
}
} for(int i=;i<=n;i++)
r(x),s=T,t=i,
adde(s,t,x);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
r(x),
s=(i-)*n+j,t=(i-)*n+j,
adde(s,t,x);
for(int i=;i<=n;i++)
r(x),
s=(n-)*n+i,t=S,
adde(S,t,x); for(int i=;i<=n;i++)
for(int j=;j<=n+;j++){
r(x);
if(j==){
s=(i-)*n+j;t=S;
adde(S,t,x);
}
else if(j==n+){
s=T;t=i*n;
adde(s,t,x);
}
else{
s=j+(i-)*n;t=j+(i-)*n-;
adde(s,t,x);
}
}
dijkstra();
return ;
}

网络流

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
#define ll long long
#define N 1705
using namespace std;
int n,S,T,tot,mp[N][N],cur[N],vis[N],d[N],hd[N];
int dx[]={,,,-};
int dy[]={,-,,};
bool check(int x,int y){return x<=n&&y<=n&&x>=&&y>=;}
struct edge{int v,cap,next;}e[N*N*];
void adde(int u,int v,int c){
e[tot].v=v;
e[tot].next=hd[u];
e[tot].cap=c;
hd[u]=tot++;
}
bool bfs(){
queue<int>q;
memset(vis,,sizeof(vis));
q.push(S);d[S]=;vis[S]=;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=hd[u];~i;i=e[i].next){
int v=e[i].v;
if(e[i].cap&&!vis[v]){
vis[v]=;
d[v]=d[u]+;
q.push(v);
}
}
}
return vis[T];
} int dfs(int u,int a){
if(u==T||!a)return a;
int fl=,f;
for(int &i=cur[u];~i;i=e[i].next){
int v=e[i].v;
if(e[i].cap&&d[v]==d[u]+&&(f=dfs(v,min(a,e[i].cap)))){
fl+=f;a-=f;
e[i].cap-=f;
e[i^].cap+=f;
if(!a)break;
}
}
return fl;
}
int main(){
#ifdef wsy
freopen("data.in","r",stdin);
#else
freopen("altitude.in","r",stdin);
freopen("altitude.out","w",stdout);
#endif
scanf("%d",&n);
memset(hd,-,sizeof(hd));
for(int i=;i<=n+;i++){
for(int j=;j<=n;j++){
int cnt=(i-)*(n+)+j;
scanf("%d",&mp[cnt][cnt+]);
}
}
for(int i=;i<=n;i++){
for(int j=;j<=n+;j++){
int cnt=(i-)*(n+)+j;
scanf("%d",&mp[cnt][cnt+n+]);
}
}
for(int i=;i<=n+;i++){
for(int j=;j<=n;j++){
int cnt=(i-)*(n+)+j;
scanf("%d",&mp[cnt+][cnt]);
}
}
for(int i=;i<=n;i++){
for(int j=;j<=n+;j++){
int cnt=(i-)*(n+)+j;
scanf("%d",&mp[cnt+n+][cnt]);
}
}
n++;S=;T=n*n+;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
int id=(i-)*n+j;
if(id==n*n)continue;
for(int o=;o<;o++){
int nx=i+dx[o];
int ny=j+dy[o];
if(!check(nx,ny))continue;
int nd=(nx-)*n+ny;
//if(nd==1)continue;
adde(id,nd,mp[id][nd]);
adde(nd,id,);
// printf("%d %d %d\n",id,nd,mp[id][nd]);
}
}
adde(S,,inf);adde(,S,);
// printf("%d %d %d\n",S,1,inf);
adde(n*n,T,inf);adde(T,n*n,);
// printf("%d %d %d\n",n*n,T,inf);
int flow=;
while(bfs()){
for(int i=S;i<=T;i++)cur[i]=hd[i];
flow+=dfs(S,inf);
}
printf("%d",flow);
return ;
}

bzoj2007 NOI2010 网络流转对偶图的更多相关文章

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

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

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

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

  3. bzoj2007 NOI2010 海拔(对偶图)

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

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

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

  5. BZOJ1001 狼抓兔子(网络流转最短路:对偶图)

    题意: 给一个如图形式的\(n*m\)的方格,从左上走到右下,给出边权,问分成两块所需的最小代价.\(n,m\leq1000\). 思路: 显然是个最小割,但是\(O(n^2m)\)的复杂度很高,虽然 ...

  6. Bzoj2007 [Noi2010]海拔(平面图最短路)

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2742  Solved: 1318[Submit][Status] ...

  7. BZOJ2007——[Noi2010]海拔

    1.题意:一个裸的最小割 2.分析:直接转成对偶图最短路就好了,水爆了!(雾) #include <queue> #include <cstdio> #include < ...

  8. bzoj千题计划129:bzoj2007: [Noi2010]海拔

    http://www.lydsy.com/JudgeOnline/problem.php?id=2007 1.所有点的高度一定在0~1之间, 如果有一个点的高度超过了1,那么必定会有人先上坡,再下坡, ...

  9. 如何将网络流转化为内存流 C#

    //将获取的文件流转化为内存流 public static MemoryStream ConvertStreamToMemoryStream(Stream stream) { MemoryStream ...

随机推荐

  1. JS页面跳转的常用方法整理.

    <script type="text/javascript"> //js页面跳转 function showtabs() { window.location.href ...

  2. JAVA_SE基础——57.有了包之后类与类之间的访问使用import语句

    代码1访问代码2 代码1: class Demo3 { public static void main(String[] args) { Demo4 a = new Demo4(); a.print( ...

  3. JAVA_SE基础——19.数组的定义

    数组是一组相关数据的集合,数组按照使用可以分为一维数组.二维数组.多维数组 本章先讲一维数组 不同点: 不使用数组定义100个整形变量:int1,int2,int3;;;;;; 使用数组定义 int ...

  4. python 字符串和字典

    一.字符串操作 name = "my name is \t {name} and i am {year} years old" 1.首字母大写 print(name.capital ...

  5. 算法题丨Two Sum

    描述 Given an array of integers, return indices of the two numbers such that they add up to a specific ...

  6. python之celery的使用(一)

    前段时间需要使用rabbitmq做写缓存,一直使用pika+rabbitmq的组合,pika这个模块虽然可以很直观地操作rabbitmq,但是官方给的例子太简单,对其底层原理了解又不是很深,遇到很多坑 ...

  7. axure 预览"HTTP/1.1 302 Found"

    使用Axure编辑原型时,点击预览出现"HTTP/1.1 302 Found" 第一想到的就是重新安装Axure和检查原型文件是否损坏,验证后证明前Axure和.rp文件都是完好的 ...

  8. C# 客户端程序调用外部程序的三种实现

    简介 我们用C#来开发客户端程序的时候,总会不可避免的需要调用外部程序或者访问网站,本篇博客介绍了三种调用外部应用的方法,供参考 实现 第一种是利用shell32.dll,实现ShellExecute ...

  9. jenkins创建multibranch pipeline

    参考以下文章进行实践: https://jenkins.io/doc/pipeline/tour/hello-world/#what-is-a-jenkins-pipeline (看见一个介绍的还不错 ...

  10. python基础二(基础数据类型)

    一. 引子 1. 什么是数据 x=10,10是我们要存储的数据 2. 为何数据要分不同的类型 数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示 3.数据类型 数字 字符串 列表 元组 字 ...