
考虑随意割边,发现割的边所构成的面应该是相邻的,倘若不相邻就说明还可以再通。

比如说这样。
那么只要选择一条最短路径就好了(即最小割)
那么为什么不是从左上走出去呢?
或许可以理解为本来平面图就是左上到右下,割的显然不能平行(左上到右下),要有交才算割(大雾),不过知道相反就好了。
https://darkbzoj.cc/problem/1001
有点卡常,别 #define int long long
#include <bits/stdc++.h>
#define ll long long
using namespace std;
inline int rd() {
int sum=0,f=1; char ch=getchar();
while(ch>'9'||ch<'0') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0') {
sum=sum*10+ch-'0'; ch=getchar();
}
return sum*f;
}
const int N=(int)(2e6+5),M=1005;
struct edge {
int nex,to,w;
}e[N*30];
int n,m,s1[M][M],s2[M][M],s3[M][M],id[2][M][M];
int hea[N],cnt,S,T;
void add_edge(int x,int y,int z) {
e[++cnt].nex=hea[x]; e[cnt].to=y; e[cnt].w=z; hea[x]=cnt;
}
void add(int x,int y,int z) {
add_edge(x,y,z); add_edge(y,x,z);
}
struct node {
int x; ll d;
node(int xx,ll dd) {
x=xx; d=dd;
}
bool operator < (const node &rhs) const {
return d>rhs.d;
}
};
const ll inf=(ll)(2e18);
priority_queue<node>q;
bool vis[N];
ll dis[N];
void dij() {
for(int i=0;i<=T;i++) dis[i]=inf;
dis[S]=0; q.push(node(S,0));
while(!q.empty()) {
int x=q.top().x; q.pop();
if(vis[x]) continue ;
vis[x]=1;
for(int i=hea[x];i;i=e[i].nex) {
int y=e[i].to;
if(dis[y]>dis[x]+e[i].w) {
dis[y]=dis[x]+e[i].w;
if(!vis[y]) q.push(node(y,dis[y]));
}
}
}
}
signed main() {
n=rd(); m=rd();
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++) s1[i][j]=rd();
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++) s2[i][j]=rd();
for(int i=1;i<n;i++)
for(int j=1;j<m;j++) s3[i][j]=rd();
if(n==1) {
int qwq=(int)(2e9);
for(int i=1;i<m;i++) qwq=min(qwq,s1[1][i]);
cout<<qwq; return 0;
}
if(m==1) {
int qwq=(int)(2e9);
for(int i=1;i<n;i++) qwq=min(qwq,s2[i][1]);
cout<<qwq; return 0;
}
int tot=0;
for(int i=1;i<n;i++)
for(int j=1;j<m;j++) {
id[0][i][j]=++tot; id[1][i][j]=++tot;
}
S=0; ++tot; T=tot;
for(int i=1;i<n;i++) {
add(S,id[0][i][1],s2[i][1]);
}
for(int i=1;i<m;i++) {
add(S,id[0][n-1][i],s1[n][i]);
}
for(int i=1;i<m;i++) {
add(id[1][1][i],T,s1[1][i]);
}
for(int i=1;i<n;i++) {
add(id[1][i][m-1],T,s2[i][m]);
}
for(int i=1;i<n;i++) {
for(int j=1;j<m;j++) {
add(id[0][i][j],id[1][i][j],s3[i][j]);
if(i+1<n) add_edge(id[0][i][j],id[1][i+1][j],s1[i+1][j]);
if(i-1>=1) add_edge(id[1][i][j],id[0][i-1][j],s1[i][j]);
if(j+1<m) add_edge(id[1][i][j],id[0][i][j+1],s2[i][j+1]);
if(j-1>=1) add_edge(id[0][i][j],id[1][i][j-1],s2[i][j]);
}
}
dij();
cout<<dis[T];
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】