正解:网络流+对偶图
解题报告:
$umm$之前省选前集训的时候叶佬考过?然而这和我依然不会做有什么关系呢$kk$
昂这题首先要两个结论?第一个是说每个位置的海拔一定是0/1,还一个是说0/1一定都是连通块$QwQ$
瞎证下?$QwQ$.
结论一:若存在海拔大于1的点,下坡不变,上坡代价增加,显然改为1更优
若存在海拔在0到1之间的点,同样理由,发现改为0更优
结论二有点显然的亚子,,,懒得证了趴$QwQ$
欧克然后现在这道题就变成一个最小割了?
但是$n$的范围是500,,,显然会$T$昂$QAQ$.
然后就考虑,转对偶图求最短路
恩因为只是个技巧类的姿势点所以我就懒得写学习笔记辣,网上随便一搜就成鸭$QwQ$
简单总结下就,平面图上的最大流等价于对偶图的最短路,构建对偶图的方法是把每对相邻面连接起来,边权为穿过的边界的流量.跑个最短路.$over$
然后由上面两个结论得这个图确实是个平面图,所以转化成对偶图求个最短路就做完了$QwQ$?
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define fi first
#define sc second
#define gc getchar()
#define mp make_pair
#define P pair<int,int>
#define t(i) edge[i].to
#define w(i) edge[i].wei
#define ri register int
#define rb register bool
#define rc register char
#define rp(i,x,y) for(ri i=x;i<=y;++i)
#define my(i,x,y) for(ri i=x;i>=y;--i)
#define e(i,x) for(ri i=head[x];i;i=edge[i].nxt)
const int N=2500+10;
int n,ed_cnt,head[N*N],S,T,dis[N*N];
struct ed{int to,nxt,wei;}edge[N*N*20];
bool vis[N*N];
il int read()
{
rc ch=gc;ri x=0;rb y=1;
while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
if(ch=='-')ch=gc,y=0;
while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
return y?x:-x;
}
il void ad(ri x,ri y,ri z){edge[++ed_cnt]=(ed){x,head[y],z};head[y]=ed_cnt;}
il int nam(ri x,ri y){if(!x)return T;if(y>n)return T;if(!y)return S;if(x>n)return S;return (x-1)*n+y;}
il void dij()
{
priority_queue< P,vector<P>,greater<P> >Q;Q.push(mp(0,S));memset(dis,63,sizeof(dis));
while(!Q.empty())
{
ri nw=Q.top().sc,diss=Q.top().fi;Q.pop();if(vis[nw])continue;vis[nw]=1;dis[nw]=diss;
e(i,nw)if(!vis[t(i)])Q.push(mp(dis[nw]+w(i),t(i)));
}
}
int main()
{
n=read();T=n*n+1;
rp(i,1,n+1)rp(j,1,n)ad(nam(i-1,j),nam(i,j),read());
rp(i,1,n)rp(j,1,n+1)ad(nam(i,j),nam(i,j-1),read());
rp(i,1,n+1)rp(j,1,n)ad(nam(i,j),nam(i-1,j),read());
rp(i,1,n)rp(j,1,n+1)ad(nam(i,j-1),nam(i,j),read());
dij();printf("%d\n",dis[T]);
return 0;
}