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 ;
}

最新文章

  1. 如何使用videojs兼容IE8浏览器
  2. 测试markdown
  3. 【转】你真的了解word-wrap和word-break的区别吗?
  4. Linux下C程序的编译,运行,及调试
  5. Silverlight引用WebService时取消对ServiceReferences.ClientConfig文件的依赖
  6. JDBC连接数据库代码
  7. EPEL库安装
  8. AngularJS 通过 Spring Restful 上传文件
  9. VMware虚拟机三种网络模式的区别(上篇)
  10. Hibernate学习
  11. memory引擎的索引失效一例
  12. XLink and XPoint
  13. Python 官方文档解读(1):66 个内置函数
  14. windows C 盘大小异常增大并解决记录
  15. Mysql查询正在运行的事务
  16. Asp.Net MVC向视图View传值的三种方法
  17. 这几天用高通VUFORIA的体会
  18. Drbd双机环境安装配置
  19. 使用Goland同步远程代码
  20. C# NPOI操作Excel(下)

热门文章

  1. JAVA_SE基础——2.环境变量的配置&测试JDK
  2. 流程控制语句(MySQL/MariaDB )
  3. JQ.ajax 各种参数及属性设置 ( 转载 )
  4. hibernate_exercise-many- to-one(1)
  5. Linux入门:vi 和 vim
  6. SpringCloud用户自定义配置信息的定义和查看
  7. Spring MVC拦截器的配置
  8. 实现GridControl行动态改变行字体和背景色
  9. JavaScript的基础学习
  10. uva 11636 Hello World!