很明显直接最大流就炸飞了啊qvq
首先引入对偶图的概念
能看懂的传送门
所以对偶图最短路 = 原图最小割 = 原图最大流
这道题就瞬间裸起来了
手动建一下对偶图 建图跑最短路即可
//之前数组开小了
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
const long long inf = 0x7fffffff;
const int N = 1e3 + 5;
const int M = 2 * N * N;
struct Edge{
int v, w, next;
}edge[N * N * 6];
int esize, head[M];
inline void addedge(int x, int y, int z){
edge[++esize] = (Edge){y, z, head[x]};
head[x] = esize;
}
struct Node{
long long dis;
int x;
friend bool operator <(Node x, Node y){
return x.dis > y.dis;
}
};
priority_queue<Node> q;
bool vis[M];
long long dis[M];
int n, m, S, T;
int pre[M];
void dijkstra(){
q.push((Node){0, S});
memset(dis, 0x3f, sizeof(dis));
int fro; dis[S] = 0;
while(!q.empty()){
do{fro = q.top().x; q.pop();
}while(vis[fro] && !q.empty());
vis[fro] = 1;
for(int i = head[fro], vv; ~i; i = edge[i].next){
vv = edge[i].v;
if(dis[vv] > dis[fro] + edge[i].w){
pre[vv] = fro;
dis[vv] = dis[fro] + edge[i].w;
q.push((Node){dis[vv], vv});
}
}
}
}
int main(){
// freopen("testdata.in", "r", stdin);
memset(head, -1, sizeof(head));
int x;
scanf("%d%d", &n, &m);
if(n == 1 || m == 1){
long long x, mn = inf;
for(int i = 1; i <= max(m, n); ++i){
scanf("%lld", &x); mn = min(mn, x);
}
printf("%lld", mn);
return 0;
}
S = 2 * (n - 1) * (m - 1) + 1, T = 2 * (n - 1) * (m - 1) + 2;
//
for(int i = 1; i <= m - 1; ++i){
scanf("%d", &x);
addedge(i, T, x);
}
for(int i = 1, k1 = 2 * (m - 1), k2 = m - 1; i <= n - 2; ++i)
for(int j = 1; j <= m - 1; ++j){
scanf("%d", &x);
addedge(k1 * i - k2 + j, k1 * i + j, x);
addedge(k1 * i + j, k1 * i - k2 + j, x);
}
for(int i = 1, k = 2 * (n - 1) * (m - 1) - (m - 1); i <= m - 1; ++i){
scanf("%d", &x);
addedge(S, k + i, x);
}
//
for(int i = 1, k1 = 2 * (m - 1), k2 = m - 1; i <= n - 1; ++i){
scanf("%d", &x);
addedge(S, i * k1 - k2 + 1, x);
for(int j = 2; j <= m - 1; ++j){
scanf("%d", &x);
addedge((i - 1) * k1 + j - 1, i * k1 - k2 + j, x);
addedge(i * k1 - k2 + j, (i - 1) * k1 + j - 1, x);
}
scanf("%d", &x);
addedge(i * k1 - k2, T, x);
}
//
for(int i = 1, k1 = 2 * (m - 1), k2 = m - 1; i <= n - 1; ++i)
for(int j = 1; j <= m - 1; ++j){
scanf("%d", &x);
addedge((i - 1) * k1 + j, i * k1 - k2 + j, x);
addedge(i * k1 - k2 + j, (i - 1) * k1 + j, x);
}
dijkstra();
printf("%lld", dis[T]);
return 0;
}