题解
平面图最小割,转化为对偶图跑最短路即可。这个网上随便搜一下题解满天飞。
代码:
//BZOJ 1001
#include<iostream>
#include<cstdio>
#include<cstring>
#include<climits>
#include<queue>
#define INF (LLONG_MAX/3)
#define P(i,j) (((i)-1)*(m-1)+(j))
#define Q(i,j) (P(i,j)+(n-1)*(m-1))
#define MAXN 2000100
#define MAXM 10000000
#define lint long long
using namespace std;
struct edges{
int to,wgt,pre;
}e[MAXM];
int etop,h[MAXN];
struct node{
int id;lint dist;
node(int _i,int _d)
{
id=_i;
dist=_d;
}
bool operator<(const node &n)const
{
return this->dist>n.dist;
}
};
inline int add_edge(int u,int v,int w)
{
etop++;
e[etop].to=v;
e[etop].wgt=w;
e[etop].pre=h[u];
h[u]=etop;
return 0;
}
inline int build_edge(int u,int v,int w)
{
add_edge(u,v,w);add_edge(v,u,w);return 0;
}
priority_queue<node> q;
lint dist[MAXN];bool vis[MAXN];
int dijkstra(int s,int t,int n)
{
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++) dist[i]=INF;
while(!q.empty()) q.pop();
q.push(node(s,dist[s]=0));
while(!q.empty())
{
int x=q.top().id;q.pop();
if(vis[x]) continue;vis[x]=true;
for(int i=h[x];i;i=e[i].pre)
if(!vis[e[i].to]&&dist[x]+e[i].wgt<dist[e[i].to])
{
dist[e[i].to]=dist[x]+e[i].wgt;
q.push(node(e[i].to,dist[e[i].to]));
}
}
return 0;
}
int main()
{
int n,m;scanf("%d%d",&n,&m);
int s=2*(n-1)*(m-1)+1,t=s+1;
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++)
{
int w,f=0;scanf("%d",&w);
if(i==1) build_edge(s,P(i,j),w),f=1;
if(i==n) build_edge(Q(i-1,j),t,w),f=1;
if(!f) build_edge(P(i,j),Q(i-1,j),w);
}
for(int i=1;i<n;i++)
for(int j=1;j<=m;j++)
{
int w,f=0;scanf("%d",&w);
if(j==1) build_edge(Q(i,j),t,w),f=1;
if(j==m) build_edge(P(i,j-1),s,w),f=1;
if(!f) build_edge(P(i,j-1),Q(i,j),w);
}
for(int i=1;i<n;i++)
for(int j=1;j<m;j++)
{
int w;scanf("%d",&w);
build_edge(P(i,j),Q(i,j),w);
}
dijkstra(s,t,2*(n-1)*(m-1)+2);
printf("%lld\n",dist[t]);return 0;
}