题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2007

一个点的高度一定不是0就是1。答案一定形如一个左上角的连通块全是0的点、一个右下角的连通块全是1的点。

注意从东到西还有从南到北的边也有用!因为不一定是一个阶梯形的,还可以拐来拐去,只是一定是两个连通块罢了。

所以最小割一下那个分界线就行了。但会TLE。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=*+,M=*+,INF=2e6+;
int n,t,bh[][],hd[N],xnt=,cur[N],to[M],nxt[M],cap[M];
int dfn[N],q[N],he,tl;
int Mn(int a,int b){return a<b?a:b;}
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
void add(int x,int y,int z)
{
to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;cap[xnt]=z;
to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;cap[xnt]=;
}
bool bfs()
{
memset(dfn,,sizeof dfn);dfn[]=;
q[he=tl=]=;
while(he<=tl)
{
int k=q[he++];
for(int i=hd[k],v;i;i=nxt[i])
if(cap[i]&&!dfn[v=to[i]])
dfn[v]=dfn[k]+,q[++tl]=v;
}
return dfn[t];
}
int dinic(int cr,int flow)
{
if(cr==t)return flow;
int use=;
for(int& i=cur[cr],v;i;i=nxt[i])
if(cap[i]&&dfn[v=to[i]]==dfn[cr]+)
{
int tmp=dinic(v,Mn(flow-use,cap[i]));
if(!tmp)dfn[v]=;
use+=tmp;cap[i]-=tmp;cap[i^]+=tmp;
if(use==flow)return use;
}
return use;
}
int main()
{
n=rdn();
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)bh[i][j]=t++;
t--; int d;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
d=rdn(),add(bh[i][j-],bh[i][j],d);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
d=rdn(),add(bh[i-][j],bh[i][j],d);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
d=rdn(),add(bh[i][j],bh[i][j-],d);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
d=rdn(),add(bh[i][j],bh[i-][j],d);
int ans=;
while(bfs())memcpy(cur,hd,sizeof hd),ans+=dinic(,INF);
printf("%d\n",ans);
return ;
}

可以转成最短路。注意边的方向。

学习了学长的不显式建图的方法。大概 dis[ ][ ] 记录的就是从起点走到格子的距离,再记4个 dis[ ][ ] 表示它的周围4条边的容量,之类的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=,INF=2e6+;
int n,dis[][N][N],ans=INF;bool vis[N][N];
struct Node{
int x,y,dis;
Node(int a=,int b=,int d=):x(a),y(b),dis(d) {}
bool operator< (const Node &b)const
{return dis>b.dis;}
};
priority_queue<Node> q;
int Mn(int a,int b){return a<b?a:b;}
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
void add(int x,int y,int d)
{
if(d<dis[][x][y])
dis[][x][y]=d,q.push(Node(x,y,d));
}
void dj()
{
for(int i=;i<=n;i++)add(,i,dis[][][i]);
for(int i=;i<=n;i++)add(i,n,dis[][i][n+]);
while(q.size())
{
int x=q.top().x,y=q.top().y,d=q.top().dis; q.pop();
if(vis[x][y])continue; vis[x][y]=;
if(x<n)add(x+,y,d+dis[][x+][y]);//x+1(up)
if(y>)add(x,y-,d+dis[][x][y]);
if(x>)add(x-,y,d+dis[][x-][y]);//x-1(dn)
if(y<n)add(x,y+,d+dis[][x][y]);
}
for(int i=;i<=n;i++)ans=Mn(ans,dis[][i][]+dis[][i][]);
for(int i=;i<=n;i++)ans=Mn(ans,dis[][n][i]+dis[][n+][i]);//n+1
}
int main()
{
n=rdn();int d=n+;
for(int i=;i<=d;i++)
for(int j=;j<=n;j++)dis[][i][j]=rdn();//up
for(int i=;i<=n;i++)
for(int j=;j<=d;j++)dis[][i][j]=rdn();//left
for(int i=;i<=n;i++)//0~n & 1~n !!!
for(int j=;j<=n;j++)dis[][i][j]=rdn();//dn
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)dis[][i][j]=rdn();//right
memset(dis[],0x3f,sizeof dis[]);
dj();
printf("%d\n",ans);
return ;
}

bzoj 2007 [Noi2010]海拔——最小割转最短路的更多相关文章

  1. BZOJ.2007.[NOI2010]海拔(最小割 对偶图最短路)

    题目链接 想一下能猜出,最优解中海拔只有0和1,且海拔相同的点都在且只在1个连通块中. 这就是个平面图最小割.也可以转必须转对偶图最短路,不然只能T到90分了..边的方向看着定就行. 不能忽略回去的边 ...

  2. 【bzoj2007】[Noi2010]海拔 最小割+对偶图+最短路

    题目描述 YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作一个正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1)×(n+1)个交 ...

  3. BZOJ 2007: [Noi2010]海拔

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2410  Solved: 1142[Submit][Status] ...

  4. [BZOJ 2007] [Noi2010] 海拔 【平面图最小割(对偶图最短路)】

    题目链接:BZOJ - 2007 题目分析 首先,左上角的高度是 0 ,右下角的高度是 1.那么所有点的高度一定要在 0 与 1 之间.然而选取 [0, 1] 的任何一个实数,都可以用整数 0 或 1 ...

  5. bzoj 2007: [Noi2010]海拔【最小割+dijskstra】

    上来就跑3e5的最大流--脑子抽了 很容易看出,每个地方的海拔都是0或1因为再高了没有意义,又,上去下来再上去没有意义,所以最后一定是从s连着一片0,剩下连着t一片1,然后有贡献的就是01交接的那些边 ...

  6. BZOJ 2007 NOI2010 海拔高度 最小减产计划

    标题效果:YT城市是一个精心规划的城市.这个城市是东西向和南北向干道成n×n地区性.简单.可以YT作为一个城市广场,每个区域也可被视为一个正方形.因此,.YT市中含有(n+1)×(n+1)交叉口和2n ...

  7. [NOI2010]海拔(最小割)

    题目描述 YT市是一个规划良好的城市,城市被东西向和南北向的主干道划分为n×n个区域.简单起见,可以将YT市看作一个 正方形,每一个区域也可看作一个正方形.从而,YT城市中包括(n+1)×(n+1)个 ...

  8. [NOI2010]海拔——最小割+对偶图

    题目链接 SOLUTION 想一下最优情况下肯定让平路或下坡尽量多,于是不难想到这样构图:包括左上角的一部分全部为\(0\),包括右下角的一部分全部为\(1\),于是现在问题转化为求那个分界线是什么. ...

  9. 【BZOJ 2007】 2007: [Noi2010]海拔 (平面图转对偶图+spfa)

    2007: [Noi2010]海拔 Time Limit: 20 Sec  Memory Limit: 552 MBSubmit: 2504  Solved: 1195 Description YT市 ...

随机推荐

  1. 20145311实验五"Java网络编程及安全"

    20145311实验五 "Java网络编程及安全" 程序设计过程 实验内容 ·掌握Socket程序的编写:·掌握密码技术的使用:·设计安全传输系统 ·利用加解密代码包,编译运行代码 ...

  2. Anchor、Dock

    转:http://blog.sina.com.cn/s/blog_7f7cd96601013trt.html 在设计可供用户调整大小的窗体时,如何实现该窗体上的控件也应能正确地随窗体的改变而自动调整大 ...

  3. ssh-copy-id使用非默认22端口

    ssh-copy-id使用及非默认22端口时报错 ssh-copy-id使用介绍 说明:ssh-copy-id命令可以把本地的ssh公钥文件安装到远程主机对应的账户下. 功能:ssh-copy-id ...

  4. linux kernel 提示VFS: Cannot open root device "mmcblk0p1" or unknown-block(179,1): error -19等信息后发生panic

    一.背景 文件系统安装在sd卡的第一个分区中,使用的是ext4文件系统,linux内核版本为4.14 二.思考 在内核启动之前,uboot给内核传递了参数root=/dev/mmcblk0p1,但是为 ...

  5. 2012NOIP模拟试题

    做的时候觉得这套题好简单,结果一看发现是2012年的模拟题,估计就是普及+的难度吧,AK无压力 总结 第一题状压我智障的调了好几分钟,因为我的最终状态写的1<<n,智障了 第三题的dfs调 ...

  6. 子网掩码与ip有实际关系吗?

    子网掩码是作为ip地址的标识,还是本身就是ip地址的一部分?例如10.10.10.1/24和10.10.10.1/25是同一个ip地址吗? 作者:知乎用户链接:https://www.zhihu.co ...

  7. QT 正则表达式无效

    背景:写了一个判断IP地址合法的正则表达式,并让它应用在输入框中 代码如下 QRegExp rx_ip("^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}( ...

  8. python 正则匹配字符串里面的字符

    import re x=re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') print(x)

  9. UVA-1610 Party Games (构造)

    题目大意:给出一系列字符串,构造出一个字符串大于等于其中的一半,小于另一半. 题目分析:取大小为中间的两个a,b(a<b).实际上就是找出第一个小于b的同时大于等于a的字符串,直接构造即可.要注 ...

  10. UVA-10129 Play on Words (判断欧拉道路的存在性)

    题目大意:给出一系列单词,当某个单词的首字母和前一个单词的尾字母相同,则这两个单词能链接起来.给出一系列单词,问是否能够连起来. 题目分析:以单词的首尾字母为点,单词为边建立有向图,便是判断图中是否存 ...