Luogu P2046 [NOI2010]海拔
Link
显然所有点的高度都是\(0/1\)。
不难发现高度为\(0\)的点和高度为\(1\)的点的分界线是一个割,同时只有在分界线上的边才会有代价,因此我们要求的就是最小割。
而平面图的最小割等于其对偶图的最短路,dijkstra即可。
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<utility>
#include<functional>
using pi=std::pair<int,int>;
const int N=250007;
char ibuf[(1<<23)+1],*iS=ibuf;int dis[N],vis[N];
std::vector<pi>e[N];std::priority_queue<pi,std::vector<pi>,std::greater<pi>>q;
int read(){int x=0;while(isspace(*iS))++iS;while(isdigit(*iS))(x*=10)+=*iS++&15;return x;}
void add(int u,int v,int w){e[u].push_back({v,w});}
int main()
{
fread(ibuf,1,1<<23,stdin);
int n=read(),s=n*n+1,t=n*n+2;
for(int i=0;i<=n;++i) for(int j=1;j<=n;++j) !i? add(j,t,read()):i==n? add(s,(i-1)*n+j,read()):add(i*n+j,(i-1)*n+j,read());
for(int i=1;i<=n;++i) for(int j=0;j<=n;++j) !j? add(s,(i-1)*n+1,read()):j==n? add(i*n,t,read()):add((i-1)*n+j,(i-1)*n+j+1,read());
for(int i=0;i<=n;++i) for(int j=1;j<=n;++j) !i? add(t,j,read()):i==n? add((i-1)*n+j,s,read()):add((i-1)*n+j,i*n+j,read());
for(int i=1;i<=n;++i) for(int j=0;j<=n;++j) !j? add((i-1)*n+1,s,read()):j==n? add(t,i*n,read()):add((i-1)*n+j+1,(i-1)*n+j,read());
memset(dis+1,0x3f,t<<2),q.push({dis[s]=0,s});
for(int u;!q.empty();)
{
u=q.top().second,q.pop();if(vis[u])continue;vis[u]=1;
for(auto[v,w]:e[u]) if(dis[v]>dis[u]+w) q.push({dis[v]=dis[u]+w,v});
}
printf("%d",dis[t]);
}