bzoj#1001. [BeiJing2006]狼抓兔子&感性理解一下平面图最小割=对偶图最短路

image

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

image

比如说这样。

那么只要选择一条最短路径就好了(即最小割)

那么为什么不是从左上走出去呢?

或许可以理解为本来平面图就是左上到右下,割的显然不能平行(左上到右下),要有交才算割(大雾),不过知道相反就好了。

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__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16503985.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示