【平面图最小割】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\n",dijkstra());
100     return 0;
101 } 
时间: 2024-12-24 04:59:38

【平面图最小割】BZOJ2007-[NOI2010]海拔的相关文章

【BZOJ2007】【Noi2010】海拔 平面图最小割转最短路

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43280891"); } 题解:这个模型很水,不需要极角序神马转对偶图,直接乱搞就行. 然后目的是把图割开,那么只需要跑S->T最短路就行. 要做平面图转对偶图不妨去这篇. [BZOJ2965]保护古迹 平面图转对偶图,暴力,网络流 还有就是某人

BZOJ 2007 海拔(平面图最小割-最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2007 题意:给出一个n*n的格子,那么顶点显然有(n+1)*(n+1)个.每两个相邻顶点之间有两条边,这两条边是有向的,边上有权值..左上角为源点,右下角为汇点,求s到t的最小割. 思路:很明显这是一个平面图,将其转化为最 短路.我们将s到t之间连一条边,左下角为新图的源点S,右上角区域为新图的终点T,并且为每个格子编号.由于边是有向的,我们就要分析下这条边应该是哪 个点向哪个点的边.

[bzoj1001][BeiJing2006]狼抓兔子-题解[平面图最小割转最短路]/[Dinic求最小割]

Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的, 而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形: 左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路

平面图最小割 对偶图

平面图最小割 对偶图: 平面图G的性质: (1)满足n个点,m条边,f个面 f = m - n + 2; (2)存在与其对应的对偶图G*; 对偶图:将原图中每个面变成一个点,外边界的无限大的面看成一个点,后连线即成对偶图: G的面数等于G*的点数,边数相等: 详解请看 最大最小定理(平面图最小割 对偶图)周冬 对于平面图的最大流(最小割)只需转化为对偶图,直接跑最短路即可: ps:觉得建图是最复杂的,各种RE(边数就是原来的边数,只是点数变成了原来的面数,,不注意就RE了):还有现在行数列数都变

【平面图最小割】BZOJ1001- [BeiJing2006]狼抓兔子

[题目大意]左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 1:(x,y)<==>(x+1,y) 2:(x,y)<==>(x,y+1) 3:(x,y)<==>(x+1,y+1) 道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的.开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,如果一条道路上最多通过的兔子数为K,需要同样数量的K只狼伏击,求封锁道路的最小狼数. [思路]显然这是最小

tyvj P1209 - 拦截导弹 平面图最小割&amp;&amp;模型转化

P1209 - 拦截导弹 From admin    Normal (OI)总时限:6s    内存限制:128MB    代码长度限制:64KB 背景 Background 实中编程者联盟为了培养技术精湛的后备人才,必须从基础题开始训练. 描述 Description 某国为了防御敌国的导弹袭击,研发出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度.某天,雷达捕捉到敌国的导弹来袭.由于该系统还在试验阶段,所以只有

【Algorithm】平面图最小割转最短路

杭电上碰巧有几道求最小割的题目,用网络流解超时.通过离散数学中的一些知识可以将平面图最小割转化为最短路径,通过最短路解提高效率.这个转化过程很简单,但是很巧妙,详细内容可以参考<浅析最大最小定理在信息学竞赛中的应用>. 1. [HDU] 3870 Catch the Theves有一个网格拓扑,每条边都表示有$A_{ij}$个小偷,现在希望对其中一条边部署警察,使得小偷不可能偷到右下角的财宝.求至少需要多少个警察?这题是个挺有实际意义的题目,基本思路也很简单.因为题目给定小偷都从左上角出发向右

BZOJ 2007 NOI2010 海拔 平面图最小割

题目大意:YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作一个正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1)×(n+1)个交叉路口和2n×(n+1)条双向道路(简称道路),每条双向道路连接主干道上两个相邻的交叉路口.下图为一张YT市的地图(n = 2),城市被划分为2×2个区域,包括3×3个交叉路口和12条双向道路. 小Z作为该市的市长,他根据统计信息得到了每天上班高峰期间YT市每条道路两个方向的人流量,即在高峰期间沿着

Vijos1734 NOI2010 海拔 平面图最小割

建立平面图的对偶图,把最小割转化成最短路问题 Dijkstra算法堆优化 (被输入顺序搞WA了好几次T_T) 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 6 const int maxN=502; 7 const int maxV=maxN*maxN; 8 const int inf=0x3f3f3f3f; 9 10 struct E