题意就是最小割。。。。
嘛,但有个很妙的做法。。
就是对偶图。。。。。。
然后跑一遍最短路就好了。。。
#include<bits/stdc++.h>
#define MAXN 20000005
#define maxn 2005
using namespace std;
/*
原图有三种边
1.横着 就 上----下
2.竖着 左减1---》》右
3.斜着 上下两成
*/
int n,m,tot,s,t;
int h[MAXN],dis[MAXN],vis[MAXN];
struct node{
int from,to,cost,next;
}e[MAXN<<1];
void init(){
tot = s = 0;
t = MAXN - 3;
memset(h , -1 , sizeof(h));
memset(dis , 0x7f , sizeof(dis));
memset(vis , -1 , sizeof(vis));
}
void add(int x , int y , int z){
tot++;
e[tot].from = x;
e[tot].to = y;
e[tot].cost = z;
e[tot].next = h[x];
h[x] = tot;
swap(x , y);
tot++;
e[tot].from = x;
e[tot].to = y;
e[tot].cost = z;
e[tot].next = h[x];
h[x] = tot;
}
int zhuan(int x , int y){
return (x - 1) * (m -1) + y;
}
struct node2{
int x,y;
bool operator<(const node2& a) const
{
return y > a.y;
}
};
void solve(){
priority_queue<node2> q;
q.push((node2){s , 0});
dis[s] = 0;
while(!q.empty()){
node2 u = q.top();
q.pop();
if(vis[u.x] == 1)continue;
vis[u.x] = 1;
for(int i = h[u.x] ; i != (-1) ; i = e[i].next){
if(dis[e[i].to] > u.y + e[i].cost){
dis[e[i].to] = u.y + e[i].cost;
q.push((node2){e[i].to , dis[e[i].to]});
}
}
}
cout<<dis[t]<<endl;
}
int main(){
init();
cin>>n>>m;
//横向道路,第一层与终点相连,其他上接下。。。最后一层与起点向连
for(int i = 0 ; i < n ; i++){
for(int j = 1 ; j < m ; j++){
int z;cin>>z;
if(i == 0)add(j , t , z);
else if(i == n - 1)add(zhuan((i<<1) , j) , s , z);
else add(zhuan((i<<1) , j) , zhuan((i<<1) + 1 , j) , z);
}
}
//纵向道路 与上类似
for(int i = 1 ; i < n ; i++){
for(int j = 1 ; j <= m ; j++){
int z;cin>>z;
if(j == 1)add(s , zhuan((i<<1) , j) , z);
else if(j == m)add(t , zhuan((i<<1) - 1 , j - 1) , z);
else add(zhuan((i<<1) - 1 , j - 1) , zhuan((i<<1) , j) , z);
}
}
//斜向道路
for(int i = 1 ; i < n ; i++){
for(int j = 1 ; j < m ; j++){
int z;cin>>z;
add(zhuan((i<<1) - 1 , j) , zhuan((i<<1) , j) , z);
}
}
solve();
}