1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cstdlib>
5 #include <algorithm>
6 #include <queue>
7 #include <vector>
8 #define min(a, b) ((a) < (b) ? (a) : (b))
9 #define max(a, b) ((a) > (b) ? (a) : (b))
10 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
11 inline void swap(int &a, int &b)
12 {
13 int tmp = a;a = b;b = tmp;
14 }
15 inline void read(int &x)
16 {
17 x = 0;char ch = getchar(), c = ch;
18 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar();
19 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar();
20 if(c == ‘-‘) x = -x;
21 }
22
23 const int INF = 0x3f3f3f3f;
24 const int MAXN = 2100000;
25 const int MAXM = 7100000;
26
27 struct Edge
28 {
29 int v,w,nxt;
30 Edge(int _v, int _w, int _nxt){v = _v;w = _w;nxt = _nxt;}
31 Edge(){}
32 }edge[MAXM];
33 int head[MAXN + 100], cnt = 1, S = MAXN + 1, T = MAXN + 2;
34
35 inline void insert(int a, int b, int c)
36 {
37 edge[++cnt] = Edge(b,c,head[a]);
38 head[a] = cnt;
39 edge[++cnt] = Edge(a,c,head[b]);
40 head[b] = cnt;
41 }
42 int n,m;
43
44 int d[MAXN + 100], b[MAXN + 100];
45
46 struct Node
47 {
48 int u,w;
49 Node(int _u, int _w){u = _u;w = _w;}
50 Node(){}
51 };
52
53 struct cmp
54 {
55 bool operator()(Node a, Node b)
56 {
57 return a.w > b.w;
58 }
59 };
60
61 std::priority_queue<Node, std::vector<Node>, cmp> q;
62
63 void dij()
64 {
65 memset(d, 0x3f, sizeof(d));
66 d[S] = 0;
67 q.push(Node(S, 0));
68 while(q.size())
69 {
70 Node now = q.top();q.pop();
71 if(b[now.u]) continue;
72 b[now.u] = 1;
73 for(int pos = head[now.u];pos != -1;pos = edge[pos].nxt)
74 {
75 int v = edge[pos].v;
76 if(d[v] > d[now.u] + edge[pos].w)
77 {
78 d[v] = d[now.u] + edge[pos].w;
79 q.push(Node(v, d[v]));
80 }
81 }
82 }
83 }
84
85 int main()
86 {
87 memset(head, -1, sizeof(head));
88 read(n), read(m);
89 if(n == 1)
90 {
91 int ans = INF;
92 for(register int i = 1;i < m;++ i)
93 {
94 int tmp;read(tmp);
95 ans = min(ans, tmp);
96 }
97 printf("%d", ans);
98 return 0;
99 }
100 else if(m == 1)
101 {
102 int ans = INF;
103 for(register int i = 1;i < n;++ i)
104 {
105 int tmp;read(tmp);
106 ans = min(ans, tmp);
107 }
108 printf("%d", ans);
109 return 0;
110 }
111 for(register int i = 0;i < n;++ i)
112 for(register int j = 0;j < m - 1;++ j)
113 {
114 int tmp;read(tmp);
115 if(i == 0) insert(S, (i * m + j) << 1, tmp);
116 else if(i == n - 1) insert(T, ((i - 1) * m + j) << 1 | 1, tmp);
117 else insert((i * m + j) << 1, ((i - 1) * m + j) << 1 | 1, tmp);
118 }
119 for(register int i = 0;i < n - 1;++ i)
120 for(register int j = 0;j < m;++ j)
121 {
122 int tmp;read(tmp);
123 if(j == 0) insert(T, (i * m + j) << 1 | 1, tmp);
124 else if(j == m - 1) insert(S, (i * m + j - 1) << 1, tmp);
125 else insert((i * m + j) << 1 | 1, (i * m + j - 1) << 1 ,tmp);
126 }
127 for(register int i = 0;i < n - 1;++ i)
128 for(register int j = 0;j < m - 1;++ j)
129 {
130 int tmp;read(tmp);
131 insert((i * m + j) << 1, (i * m + j) << 1 | 1, tmp);
132 }
133 dij();
134 printf("%d", d[T]);
135 return 0;
136 }