大概意思就是把图分成两部分,中间交界处的边权和要最小。
裸的最小割,但是Dinic要TEL(不知道ISAP会不会)
所以就建对偶图跑最短路
#include <bits/stdc++.h>
using namespace std;
const int N = 505;
int n, head[N * N], top, S, E;
struct Rod
{
int y, nxt, w;
Rod() { }
Rod( int y, int nxt, int w ) : y(y), nxt(nxt), w(w) { }
} e[N * N * 5];
inline void Adde( int x, int y, int w )
{
e[++top] = Rod(y, head[x], w), head[x] = top;
}
struct data
{
int dis, num;
data() { }
data( int dis, int num ) : dis(dis), num(num) { }
bool operator < ( const data &a ) const
{
return dis > a.dis;
}
};
priority_queue< data > que;
bool vis[N * N];
int dis[N * N];
int Dij()
{
memset(dis, 0x3f3f3f3f, sizeof(dis));
vis[S] = 1;
dis[S] = 0;
que.push(data(0, S));
while(!que.empty())
{
int u = que.top().num;
que.pop();
for(int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].y;
if(vis[v]) continue;
if(dis[v] > dis[u] + e[i].w)
{
dis[v] = dis[u] + e[i].w;
que.push(data(dis[v], v));
}
}
}
return dis[E];
}
int pos( int x, int y )
{
if(x == 0 || y == n + 1) return S;
if(x == n + 1 || y == 0) return E;
return (x - 1) * n + y;
}
int main()
{
cin >> n;
S = 0, E = n * n + 1;
int rg;
for(int i = 0; i <= n; ++i)
for(int j = 1; j <= n; ++j)
cin >> rg, Adde(pos(i, j), pos(i + 1, j), rg);
for(int i = 1; i <= n; ++i)
for(int j = 0; j <= n; ++j)
cin >> rg, Adde(pos(i, j + 1), pos(i, j), rg);
for(int i = 0; i <= n; ++i)
for(int j = 1; j <= n; ++j)
cin >> rg, Adde(pos(i + 1, j), pos(i, j), rg);
for(int i = 1; i <= n; ++i)
for(int j = 0; j <= n; ++j)
cin >> rg, Adde(pos(i, j), pos(i, j + 1), rg);
cout << Dij() << endl;
return 0;
}