可以看出来是最小割,然后你就去求最大流了
这么大的范围就是让你用网络流卡的?咋想的啊=。=???
建议还是老老实实用 平面图最小割等于其对偶图最短路 这个东西来做吧,虽然这个东西跑的也挺慢的,最后一个点跑了$2s$
对偶图就是被边分割出来的每个区域当成一个点,然后两个区域有公共边就连边,起点和终点的问题就在源汇点中间连一条边然后就能分出来了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=2000005,M=6000005; 8 struct a{int node,dist;}; 9 bool operator < (a x,a y) 10 { 11 return x.dist>y.dist; 12 } 13 priority_queue<a> hp; 14 int p[N],noww[2*M],goal[2*M],val[2*M],dis[N],vis[N]; 15 int n,m,rd,st,ed,bs,t1,t2,cnt; 16 void Read(int &x) 17 { 18 x=0; char ch=getchar(); 19 while(!isdigit(ch)) 20 ch=getchar(); 21 while(isdigit(ch)) 22 x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); 23 } 24 void Link(int f,int t,int v) 25 { 26 noww[++cnt]=p[f],p[f]=cnt; 27 goal[cnt]=t,val[cnt]=v; 28 } 29 int ID(int a,int b,int c) 30 { 31 if(a>n||!b) return st; 32 if(!a||b>m) return ed; 33 return (a-1)*m+b+c*n*m; 34 } 35 void Dijkstra() 36 { 37 memset(dis,0x3f,sizeof dis); 38 dis[st]=0,hp.push((a){st,0}); 39 while(!hp.empty()) 40 { 41 a tt=hp.top(); hp.pop(); int tn=tt.node; 42 if(vis[tn]) continue; vis[tn]=true; 43 for(int i=p[tn];i;i=noww[i]) 44 if(dis[goal[i]]>dis[tn]+val[i]) 45 { 46 dis[goal[i]]=dis[tn]+val[i]; 47 hp.push((a){goal[i],dis[goal[i]]}); 48 } 49 } 50 } 51 int main() 52 { 53 register int i,j; 54 Read(n),Read(m); 55 n--,m--,st=2*n*m+1,ed=st+1; 56 for(i=1;i<=n+1;i++) 57 for(j=1;j<=m;j++) 58 { 59 Read(rd),t1=ID(i,j,1),t2=ID(i-1,j,0); 60 Link(t1,t2,rd),Link(t2,t1,rd); 61 } 62 for(i=1;i<=n;i++) 63 for(j=1;j<=m+1;j++) 64 { 65 Read(rd),t1=ID(i,j,0),t2=ID(i,j-1,1); 66 Link(t1,t2,rd),Link(t2,t1,rd); 67 } 68 for(i=1;i<=n;i++) 69 for(j=1;j<=m;j++) 70 { 71 Read(rd),t1=ID(i,j,0),t2=ID(i,j,1); 72 Link(t1,t2,rd),Link(t2,t1,rd); 73 } 74 Dijkstra(); printf("%d",dis[ed]); 75 return 0; 76 }