BZOJ 2007: [Noi2010]海拔

来源:互联网 发布:华为算法工程师面试 编辑:程序博客网 时间:2024/04/28 07:15

Time Limit: 20 Sec Memory Limit: 552 MB
Submit: 2694 Solved: 1294

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且所有流量均为整数。

HINT

Source


这道题输入好模糊啊啊啊,都不知道方向是先左右再上下,还是先上下再左右什么的,后来强行蒙了一个方向,终于把图建好了,所以我们对偶图建一建然后跑一下最短路就可以了。
然后这道题还要思考一个结论,什么保留整数的,都是来迷惑您的,所以我们只需要讨论在什么地方去割让图分成两半就可以了,所以显然是网络流,一看数据规模有点大,正好又是平面图,所以就转最短路吧
对偶图去剖分搞一个最小割出来即可


#include<iostream>#include<cstdio>#include<queue>#include<cstring>const int MAXN=1000000+1000;using namespace std;int n,S,T,vis[MAXN],dis[MAXN],tail,head[MAXN];struct Line{int to,flow,nxt;}line[MAXN*4];struct Situ{int u,d;bool operator<(const Situ&A) const{return d>A.d;}};priority_queue<Situ>q;void add_line(int from,int to,int flow){line[++tail].to=to;line[tail].nxt=head[from];head[from]=tail;line[tail].flow=flow;}void init(){memset(dis,127/3,sizeof(dis));q.push((Situ){S,0});dis[S]=0;}void dijkstra(){init();    while(!q.empty()){        int u=q.top().u;q.pop();        if(!vis[u]){            vis[u]=1;            for(register int i=head[u];i;i=line[i].nxt){                int v=line[i].to;                if(dis[u]+line[i].flow<dis[v]){                    dis[v]=dis[u]+line[i].flow;                    q.push((Situ){v,dis[v]});                }            }        }    }    printf("%d\n",dis[T]);}int loc(int x,int y){    if(y==0||x==n+1) return S;    if(x==0||y==n+1) return T;    else             return (x-1)*n+y;}int main(){    freopen("altitude.in","r",stdin);     freopen("altitude.out","w",stdout);    int tmp;    scanf("%d",&n);S=0;T=n*n+1;    for(register int i=0;i<=n;i++){        for(register int j=1;j<=n;j++){            scanf("%d",&tmp);            add_line(loc(i+1,j),loc(i,j),tmp);        }    }    for(register int i=1;i<=n;i++){        for(register int j=0;j<=n;j++){            scanf("%d",&tmp);            add_line(loc(i,j),loc(i,j+1),tmp);        }    }    for(register int i=0;i<=n;i++){        for(register int j=1;j<=n;j++){            scanf("%d",&tmp);            add_line(loc(i,j),loc(i+1,j),tmp);        }    }    for(register int i=1;i<=n;i++){        for(register int j=0;j<=n;j++){            scanf("%d",&tmp);            add_line(loc(i,j+1),loc(i,j),tmp);        }    }     dijkstra();    return 0;}

这里写图片描述

原创粉丝点击