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

    来自FallDream的博客,未经允许,请勿转载,谢谢。 

    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想知道在
    最理想的情况下(即你可以任意假设其他路口的海拔高度),每天上班高峰期间所有人爬坡所消耗的总体力和的最小值。   n<=500

    自己yy一下,不难发现每个点只可能是0或者1,然后就变成了一个最小割模型。

    但是最小割并不能过,会T。发现我们按照文理分科的模型建图之后得到的是一张平面图,所以我们可以把它转换成对偶图之后跑最短路就行了。

    这个可以去网上搜一搜,或者看看bzoj1001狼抓兔子(虽然那道题可以水过),有向图的话,我们把每条边都顺时针旋转90度就行了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define S 0
    #define T 250001
    #define MN 250000
    #define pa pair<int,int>
    #define mp(x,y) make_pair(x,y) 
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    struct edge{int to,next,w;}e[1005005];
    priority_queue<pa,vector<pa>,greater<pa> >q; 
    int n,cnt=0,head[MN+5],d[MN+5];
    
    inline void ins(int f,int t,int w){e[++cnt]=(edge){t,head[f],w};head[f]=cnt;}
    
    inline int num(int x,int y)
    {
        if(!x||y>n) return S;
        if(x>n||!y) return T;
        return (x-1)*n+y;
    }
    
    void dij()
    {
        memset(d,63,sizeof(d));
        q.push(mp(d[S]=0,S));
        while(!q.empty())
        {
            while(!q.empty()&&q.top().first!=d[q.top().second]) q.pop();
            if(q.empty()) break;
            int x=q.top().second;q.pop();
            for(int i=head[x];i;i=e[i].next)
                if(d[x]+e[i].w<d[e[i].to])
                {
                    d[e[i].to]=d[x]+e[i].w;
                    q.push(mp(d[e[i].to],e[i].to));    
                }
        }
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n+1;i++)
            for(int j=1;j<=n;j++)
                ins(num(i-1,j),num(i,j),read());
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n+1;j++)
                ins(num(i,j),num(i,j-1),read());
        for(int i=1;i<=n+1;i++)
            for(int j=1;j<=n;j++)
                ins(num(i,j),num(i-1,j),read());
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n+1;j++)
                ins(num(i,j-1),num(i,j),read());
           dij();
        printf("%d
    ",d[T]);
        return 0;    
    }
  • 相关阅读:
    mysql备份还原
    JavaScript位移运算多个大于号的使用方法
    js with 语句的用法
    公告栏文字滚动
    Tar打包、压缩与解压缩到指定目录的方法
    域名跳转汇总文章
    linux常用命令大全
    nginx添加多站点
    linux一键安装php环境
    linux安装unzip及使用
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj2007.html
Copyright © 2011-2022 走看看