题目: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. bzoj1009 / P3193 [HNOI2008]GT考试

    P3193 [HNOI2008]GT考试 设$f[i][j]$表示主串匹配到第$i$个位置,不吉利数字匹配到第$j$个位置 $g[i][j]$表示加上某数字使子串原来最多能匹配到第$i$个数字,现在只 ...

  2. linux内核分析第四周-使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    本周作业的主要内容就是采用gcc嵌入汇编的方式调用system call.系统调用其实就是操作系统提供的服务.我们平时编写的程序,如果仅仅是数值计算,那么所有的过程都是在用户态完成的,但是我们想将变量 ...

  3. 20162314 Experiment 4 - Graph

    Experiment report of Besti course:<Program Design & Data Structures> Class: 1623 Student N ...

  4. #ZLYD团队第二周项目总结

    ZLYD团队第二周项目总结 项目进展 确定项目内容.目标.实现计划 首先确定游戏界面的游戏区域中墙的位置,绘制其图形,并通过其中的方法,返回墙壁的位置等属性. 根据豆子的位置,绘制其图形. 初始化吃豆 ...

  5. kotlin 学习感受

    目录 kotlin 学习感受 特点 优点 屎一样的缺点 总结 kotlin 学习感受 直白的说..很不好,像屎一样,本来对此抱有很大的期望和好感度,但经过一整天的学习,完全失望了,这门语言中间有各种的 ...

  6. Qt+json

    Json文件是这样: { "first fruit": { "describe":"an apple", "icon": ...

  7. OpenCV_火焰检测——完整代码

    转:http://blog.csdn.net/xiao_lxl/article/details/43307993 火焰检测小程序 前几天,偶然看到了An Early Fire-Detection Me ...

  8. The current .NET SDK does not support targeting .NET Core 3.0

    编译错误 Severity Code Description Project File Line Suppression StateError NETSDK1045 The current .NET ...

  9. Java知识弥补-Android开发

    目录 数据结构 1. Map-HashMap 2. StringBuilder 3. List-ArrayList 4. Vector 5. Stack 6. Set 由于这学期开了android课程 ...

  10. LA 4253 箭术(二分枚举)

    https://vjudge.net/problem/UVALive-4253 题意: 有n个平行于x轴的线段,每条线段代表一个靶子.判断是否可以站在x轴上[0,W]区间内的某个位置射箭. 思路:二分 ...