zoukankan      html  css  js  c++  java
  • [NOI2010]海拔(最小割)

    题目描述

    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想知道在
    最理想的情况下(即你可以任意假设其他路口的海拔高度),每天上班高峰期间所有人爬坡所消耗的总体力和的最
    小值。
    题解
    通过贪心,我们可以贪心的发现最优解左上角是0,右下角是1.
    然后我们可以建出图来,从起点到终点求一遍最小割。
    然后这数据范围不能最小割。
    然后我就忘了对偶图咋建了(就是两个相邻的平面之间连边)。
    代码
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define N 502
    #define mm make_pair
    using namespace std;
    priority_queue<pair<int,int> >q;
    bool vis[N*N];
    int id[N][N],dis[N*N],tot,head[N*N],n,top;
    inline int rd(){
        int x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct edge{int n,to,l;}e[N*N*4];
    inline void add(int u,int v,int l){
        e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
    }
    int main(){
        n=rd();int x;
        for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)id[i][j]=++top;top++;
        for(int i=1;i<=n;++i)id[i][0]=id[n+1][i]=top;
    //    for(int i=1;i<=n;++i)id[0][i]=id[i][n+1]=top;
        for(int i=1;i<=n+1;++i)
          for(int j=1;j<=n;++j){
                x=rd();add(id[i-1][j],id[i][j],x);
          }
        for(int i=1;i<=n;++i)
          for(int j=1;j<=n+1;++j){
              x=rd();add(id[i][j],id[i][j-1],x);
          }
        for(int i=1;i<=n+1;++i)
          for(int j=1;j<=n;++j){
              x=rd();add(id[i][j],id[i-1][j],x);
          }
        for(int i=1;i<=n;++i)
          for(int j=1;j<=n+1;++j){
              x=rd();add(id[i][j-1],id[i][j],x);
          }
        memset(dis,0x3f,sizeof(dis));dis[0]=0; 
        q.push(mm(0,0));
        while(!q.empty()){
            int u=q.top().second;q.pop();
            if(vis[u])continue;vis[u]=1;
            for(int i=head[u];i;i=e[i].n){
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].l){
                    dis[v]=dis[u]+e[i].l;
                    q.push(mm(-dis[v],v));
                }
            }
        }
        printf("%d",dis[top]);
        return 0;
    }
  • 相关阅读:
    权限控制
    包(package)
    this和super关键字
    成员变量的隐藏和方法重写(覆盖)
    转--htaccess语法教程 apache服务器伪静态规则教程
    转---高并发Web服务的演变——节约系统内存和CPU
    MYSQL 分表实践
    MySql主从配置实践及其优势浅谈
    一位IT牛人的十年经验之谈
    最近对Memcache的一些学习
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10230118.html
Copyright © 2011-2022 走看看