• 【平面图最小割】BZOJ2007-[NOI2010]海拔


    【题目大意】

    城市被东西向和南北向的主干道划分为n×n个区域,包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路。现得到了每天每条道路两个方向的人流量。每一个交叉路口都有海拔,每向上爬h的高度,就需要消耗h的体力。如果是下坡的话,则不需要耗费体力。城市西北角的交叉路口海拔为0,东南角的交叉路口海拔为1。现在知道每条路两个方向的人流量,在最理想的情况下(即你可以任意假设其他路口的海拔高度),求每天所有人爬坡所消耗的总体力和的最小值。

    【思路】

    显然是一个平面图最小割,最基础的平面图最小割可以参考BZOJ1002狼爪兔子。转成对偶图,跑Dijkstra+堆优化。

    问题在于,边是有向的(即两个方向的人流量是不同的),北南、南北、东西、西东应该如何对应对偶图中的方向呢?画了张图(我人生所有的画图都要献给平面图了……)

    a

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector> 
      6 #include<queue>
      7 #define S 0
      8 #define T (n*n)+1
      9 using namespace std;
     10 typedef long long ll;
     11 const int MAXN=550*550;
     12 const ll INF=1000000000;
     13 struct edge
     14 {
     15     int fr,to,len;
     16 };
     17 vector<edge> E[MAXN];
     18 int n;
     19 
     20 void addedge(int u,int v,int w)
     21 {
     22     E[u].push_back((edge){u,v,w});
     23 }
     24 
     25 int dijkstra()
     26 {
     27     priority_queue<pair<ll,ll>,vector<pair<ll,ll> >,greater<pair<ll,ll> > > que;
     28     ll dis[MAXN],vis[MAXN];
     29     memset(vis,0,sizeof(vis));
     30     for (int i=S+1;i<=T;i++) dis[i]=INF;
     31     dis[S]=0;
     32     que.push(make_pair<ll,ll>(0,S));
     33     while (!que.empty())
     34     {
     35         int head=que.top().second;que.pop();
     36         if (!vis[head])
     37         {
     38             vis[head]=1;
     39             for (int i=0;i<E[head].size();i++)
     40             {
     41                 edge Edge=E[head][i];
     42                 if (!vis[Edge.to] && dis[Edge.to]>dis[Edge.fr]+Edge.len)
     43                 {
     44                     dis[Edge.to]=dis[Edge.fr]+Edge.len;
     45                     que.push(make_pair<ll,ll>(dis[Edge.to],Edge.to));
     46                 }
     47             }
     48         }
     49     }
     50     return (dis[T]);
     51 }
     52 
     53 
     54 void init()
     55 {
     56     scanf("%d",&n);
     57     int t;
     58     for (int i=1;i<=n+1;i++)
     59         for (int j=1;j<=n;j++)
     60         {
     61             scanf("%d",&t);
     62             if (i==1) addedge((i-1)*n+j,n*n+1,t);
     63                 else if (i==n+1) addedge(0,(i-2)*n+j,t);
     64                     else addedge((i-1)*n+j,(i-2)*n+j,t);
     65         }
     66         
     67     for (int i=1;i<=n;i++)
     68          for (int j=0;j<=n;j++)
     69          {
     70             scanf("%d",&t);
     71             if (j==0) addedge(0,(i-1)*n+j+1,t);
     72                 else if (j==n) addedge(i*n,n*n+1,t);
     73                     else addedge((i-1)*n+j,(i-1)*n+j+1,t);
     74      }
     75      
     76     for (int i=1;i<=n+1;i++)
     77       for (int j=1;j<=n;j++)
     78       {
     79         scanf("%d",&t);
     80         if (i==1) addedge(n*n+1,(i-1)*n+j,t);
     81               else if (i==n+1) addedge((n-1)*n+j,0,t);
     82                   else addedge((i-2)*n+j,(i-1)*n+j,t);
     83       }     
     84       
     85     for (int i=1;i<=n;i++)
     86       for (int j=0;j<=n;j++)
     87       {
     88         scanf("%d",&t);
     89         if (j==0) addedge((i-1)*n+j+1,0,t);
     90               else if (j==n) addedge(n*n+1,(i-1)*n+j,t);
     91                   else addedge((i-1)*n+j+1,(i-1)*n+j,t);
     92       }  
     93 
     94 }
     95 
     96 int main()
     97 {
     98     init();
     99     printf("%d
    ",dijkstra());
    100     return 0;
    101 } 
  • 相关阅读:
    面试题:面试题归类 已看1 背1
    面试题:SSH项目总结 !=!=未看 没用
    面试题: 大公司面试 !=!=未看
    Java 重写paint绘图
    c语言中数组的定义和java中数组定义的一些区别
    Java GUI界面补充总结(不定期补充)
    JFrame 的层次结构 及 背景设置说明
    为什么内部类调用的外部变量必须是final修饰的?
    Java Calendar类的使用总结【转】
    String类为什么可以直接赋值
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5719966.html
Copyright © 2020-2023  润新知