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. 阿里云CentOS部署小笔记

    快毕业了,我用近两周的时间完成了一个nodeJs+Vue-Cli+Mysql的毕业设计,到了部署的时候了. 然而,博主使用Linux的经验有限得很,所以只能自己慢慢地填坑了. 一.准备工作 1)阿里云 ...

  2. (转载) ASP.NET(C#) Web Api 通过文件流下载文件到本地实例

    下载文件到本地是很多项目开发中需要实现的一个很简单的功能.说简单,是从具体的代码实现上来说的,.NET的文件下载方式有很多种,本示例给大家介绍的是ASP.NET Web Api方式返回HttpResp ...

  3. NHibernate从入门到精通系列(3)——第一个NHibernate应用程序

    内容摘要 准备工作 开发流程 程序开发 一.准备工作 1.1开发环境 开发工具:VS2008以上,我使用的是VS2010 数据库:任意关系型数据库,我使用的是SQL Server 2005 Expre ...

  4. 十个你需要在 PHP 7 中避免的坑

    1. 不要使用 mysql_ 类函数 终于,你不用再看到建议不要使用 mysql_ 函数的提示了.因为 PHP 7 从核心上完全移除了它们,这意味着请你移步至更好的 mysqli_ 类函数,或者更灵活 ...

  5. vi和vim编辑器

    VI vi是一种计算机文本编辑器,由美国计算机科学家比尔·乔伊(Bill Joy)完成编写,并于1976年以BSD协议授权发布. VIM Vim是从vi发展出来的一个文本编辑器.其代码补完.编译及错误 ...

  6. Hibernate(二):MySQL server version for the right syntax to use near 'type=InnoDB' at line x

    目前使用的hibernate5.2.9版本,配置的mysql方言为: <property name="hibernate.dialect">org.hibernate. ...

  7. c语言一个显示星号的函数(隐藏密码)

    显示星号 void star(char p[])    //显示星号 {     int j; while((p[j] = getch())!='\r') { if(p[j] !='\b') { pr ...

  8. 【转载】Ubuntu 12.04 LTS 中文输入法的安装

    原文地址 :  http://www.cnblogs.com/zhj5chengfeng/archive/2013/06/23/3150620.html 我装的是英文版的 Ubuntu12.04,如果 ...

  9. Git reset到某一次commit

    下图场景:张三和李四并行开发,张三提交commit1(bc2dd00),李四提交commit2(7f019d2),张三再提交commit3(44d4fc5),如果此时李四revert commit2, ...

  10. laydate 日期格式为yyyy 或yyyy-MM时,出现错误Uncaught TypeError: Cannot read property 'length' of undefined

    这个改起比较麻烦,没有深究,简单兼容了yyyy 和yyyy-MM,其他格式可能还是会有错误.替换Dates.check方法. //检测日期是否合法 Dates.check = function(){ ...