zoukankan      html  css  js  c++  java
  • 2007: [Noi2010]海拔

    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

    【样例说明】
    样例数据见下图。


    最理想情况下所有点的海拔如上图所示。

    【数据规模】
    对于20%的数据:n ≤ 3;

    对于50%的数据:n ≤ 15;

    对于80%的数据:n ≤ 40;

    对于100%的数据:1 ≤ n ≤ 500,0 ≤ 流量 ≤ 1,000,000且所有流量均为整数。

    一不小心就看到了是最小割233,然后就想到了最小割构图

    因为左上角是0右下角是1,所以我们海拔肯定是0或者1,于是最小割就很明显了,就是他给你的这张图,左上角为源右下角为汇

    数据太大所以我们又只能换成对偶图最短路了,可以参考bzoj1001狼与兔子,不过那是无向图,这个是有向图

    于是右→下,下→左,左→上,上→右(还成环了233),跑一遍右上到左下的最短路就行了,直接SPFA有两个点过不去,所以我加了heap

      1 const
      2     maxn=510;
      3     inf=1000000000;
      4 var
      5     first:array[0..maxn*maxn]of longint;
      6     next,last,w:array[0..maxn*maxn*4]of longint;
      7     n,tot:longint;
      8  
      9 function calc(x,y:longint):longint;
     10 begin
     11     if (x=0) or (y=n+1) then exit(0);
     12     if (x=n+1) or (y=0) then exit(n*n+1);
     13     exit((x-1)*n+y);
     14 end;
     15  
     16 procedure insert(x,y:longint);
     17 begin
     18     inc(tot);
     19     last[tot]:=y;
     20     next[tot]:=first[x];
     21     first[x]:=tot;
     22 end;
     23  
     24 var
     25     q,h,dis:array[0..maxn*maxn]of longint;
     26     flag:array[0..maxn*maxn]of boolean;
     27     r:longint;
     28  
     29 procedure swap(var x,y:longint);
     30 var
     31     t:longint;
     32 begin
     33     t:=x;x:=y;y:=t;
     34 end;
     35  
     36 procedure up(x:longint);
     37 var
     38     i:longint;
     39 begin
     40     while x>1 do
     41         begin
     42             i:=x>>1;
     43             if dis[q[x]]<dis[q[i]] then
     44                 begin
     45                     swap(q[x],q[i]);
     46                     h[q[x]]:=x;h[q[i]]:=i;
     47                     x:=i;
     48                 end
     49             else exit;
     50         end;
     51 end;
     52  
     53 procedure down(x:longint);
     54 var
     55     i:longint;
     56 begin
     57     i:=x<<1;
     58     while i<=r do
     59         begin
     60             if (i<r) and (dis[q[i+1]]<dis[q[i]]) then inc(i);
     61             if dis[q[i]]<dis[q[x]] then
     62                 begin
     63                     swap(q[i],q[x]);
     64                     h[q[x]]:=x;h[q[i]]:=i;
     65                     x:=i;i:=x<<1;
     66                 end
     67             else exit;
     68         end;
     69 end;
     70  
     71 procedure delete;
     72 begin
     73     swap(q[1],q[r]);
     74     h[q[1]]:=1;
     75     dec(r);
     76     down(1);
     77 end;
     78  
     79 procedure spfa;
     80 var
     81     i:longint;
     82 begin
     83     r:=1;q[1]:=0;flag[0]:=true;h[0]:=1;
     84     for i:=1 to n*n+1 do dis[i]:=inf;
     85     while r>0 do
     86         begin
     87             if q[1]=n*n+1 then break;
     88             i:=first[q[1]];
     89             while i<>0 do
     90                 begin
     91                     if dis[q[1]]+w[i]<dis[last[i]] then
     92                     begin
     93                         if not flag[last[i]] then
     94                         begin
     95                             inc(r);q[r]:=last[i];h[last[i]]:=r;
     96                             flag[last[i]]:=true;
     97                         end;
     98                         dis[last[i]]:=dis[q[1]]+w[i];up(h[last[i]]);
     99                     end;
    100                     i:=next[i];
    101                 end;
    102             flag[q[1]]:=false;delete;
    103         end;
    104 end;
    105  
    106 procedure main;
    107 var
    108     i,j:longint;
    109 begin
    110     read(n);
    111     for i:=1 to 4*n*(n+1) do read(w[i]);
    112     for i:=0 to n do
    113         for j:=1 to n do
    114             insert(calc(i,j),calc(i+1,j));
    115     for i:=1 to n do
    116         for j:=0 to n do
    117             insert(calc(i,j+1),calc(i,j));
    118     for i:=0 to n do
    119         for j:=1 to n do
    120             insert(calc(i+1,j),calc(i,j));
    121     for i:=1 to n do
    122         for j:=0 to n do
    123             insert(calc(i,j),calc(i,j+1));
    124     spfa;
    125     writeln(dis[n*n+1]);
    126 end;
    127  
    128 begin
    129     main;
    130 end.
    View Code
  • 相关阅读:
    安卓第一夜 第一个应用
    为什么要学习Linux
    Android的历史与花边
    来玩Play框架07 静态文件
    来玩Play框架06 用户验证
    来玩Play框架05 数据库
    来玩Play框架04 表单
    来玩Play框架03 模板
    来玩Play框架02 响应
    来玩Play框架01 简介
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3792447.html
Copyright © 2011-2022 走看看