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. Android Studio使用过程中遇到的错误

    > 错误1 1. This fragment should provide a default constructor (a public constructor wit 代码不规范,这个错误是 ...

  2. AWS中的Internet 网关

    nternet 网关是一种横向扩展.支持冗余且高度可用的 VPC 组件,可实现 VPC 中的实例与 Internet 之间的通信.因此它不会对网络流量造成可用性风险或带宽限制. Internet 网关 ...

  3. Oracle数据库游标精解

    游标 定义:标识结果集中数据行的一种容器(CURSOR),游标允许应用程序对查询语句返回的行结果集中的每一行进行相同或不同的操作,而不是一次对整个结果集进行同一种操作.实际上是一种能从包括多条数据记录 ...

  4. 如何排查CPU飙升的Java问题

    1. JPS 查看jvm进程 2. 显示线程列表 ps -mp pid -o THREAD,tid,time 找到了耗时最高的线程tid 3. tid转换成16进制 printf "%x\n ...

  5. Docker学习笔记 - Docker Compose 脚本命令

    Docker Compose 配置文件包含 version.services.networks 三大部分,最关键的是 services 和 networks 两个部分, version: '2' se ...

  6. 转:swing 中paint与paintComponent的区别(jcomponent)

    http://blog.csdn.net/q597756870/article/details/17854247 查API文档,查得在类Jcomponent下的paint方法有以下解释:        ...

  7. java中的interface

    转载: Java不支持多重继承,即一个类只能有一个父类 为了克服单继承的缺点,Java使用了接口,一个类可以实现多个接口 接口是抽象方法和常量值定义的集合,是一种特殊的抽象类接口中只包含常量和方法的定 ...

  8. 赛码网算法: 军训队列( python实现 )

    军训队列 题目描述某大学开学进行军训队列训练,将学生从一开始按顺序依次编号,并排成一行横队,训练的规则如下:从头开始一至二报数,凡报到二的出列剩下的依次向前靠拢,再从头开始进行一至三报数,凡报到三的出 ...

  9. Python之面向对象一

    引子 小游戏:人狗大战 角色:人和狗 角色属性:姓名,血量,战斗力和性别(种类) 技能:打/咬 用函数实现人打狗和狗咬人的情形 def Dog(name,blood,aggr,kind): dog = ...

  10. Android 学习资料入门到精通(PDF集合)共54本

    最近收集一些安卓入门到精通,包含游戏编程,网络编程,多媒体开发,需要学习朋友就下载保持下来,下载链接在最下面 下面是网盘内容 14天学会安卓开发_(完整版).pdf Android 4  游戏高级编程 ...