链接
题解
平面图最小割,转成对偶图最短路即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define REP(i, n) for (int i = 1; i <= (n); i++)
#define sqr(x) ((x) * (x))
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const int maxn = 500000 + 100;
// const int maxn = 50;
const int maxm = 500 + 10;
// const int maxm = 100;
const int maxt = 3000000 + 100;
const int maxk = 10 + 3;
typedef long long LL;
typedef long double LD;
typedef unsigned long long uLL;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
const LL unit = 1LL;
const int INF = 0x3f3f3f3f;
const LL Inf = 0x3f3f3f3f3f3f3f3fLL;
const double eps = 1e-4;
const double inf = 1e15;
const double pi = acos(-1.0);
const LL mod = 1000000007;
const int dir[][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
inline int read()
{
register int x = 0, t = 1;
register char ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-')
ch = getchar();
if (ch == '-')
t = -1, ch = getchar();
while (ch <= '9' && ch >= '0')
x = x * 10 + ch - 48, ch = getchar();
return x * t;
}
//n 是点的个数, m是边的个数
//st是源点
//每次AddEdge加的是有向边,无向边需加两次
struct Dijkstra
{
struct Edge
{
int from, to, dis;
};
struct HeapNode
{
int u, dis;
bool operator<(const HeapNode &a) const
{
return dis > a.dis;
}
};
int n, m;
vector<Edge> edge;
vector<int> G[maxn];
bool vis[maxn]; //是否永久标号
int dist[maxn]; //最短距离
int pre[maxn]; //最短路中上一条边
void init(int n)
{
this->n = n;
for (int i = 0; i < n; i++)
G[i].clear();
edge.clear();
}
void AddEdge(int from, int to, int d)
{
edge.push_back((Edge){from, to, d});
m = edge.size();
G[from].push_back(m - 1);
}
void dijkstra(int st)
{
priority_queue<HeapNode> que;
for (int i = 0; i < n; i++)
dist[i] = INF;
dist[st] = 0;
memset(vis, false, sizeof(vis));
que.push((HeapNode){st, 0});
while (!que.empty())
{
HeapNode x = que.top();
que.pop();
int u = x.u;
if (vis[u])
continue;
vis[u] = true;
for (int i = 0; i < G[u].size(); i++)
{
Edge &e = edge[G[u][i]];
int v = e.to;
if (dist[v] > dist[u] + e.dis)
{
dist[v] = dist[u] + e.dis;
que.push((HeapNode){v, dist[v]});
pre[v] = G[u][i];
}
}
}
}
} solver;
int n, tot;
int id[maxm][maxm];
int main()
{
n = read();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
id[i][j] = ++tot;
int st = 0, en = tot + 1;
solver.init(tot + 2);
for (int i = 1; i <= n; ++i)
id[i][0] = id[n + 1][i] = st;
for (int i = 1; i <= n; ++i)
id[0][i] = id[i][n + 1] = en;
for (int i = 1; i <= n + 1; ++i)
for (int j = 1; j <= n; ++j)
solver.AddEdge(id[i][j], id[i - 1][j], read());
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n + 1; ++j)
solver.AddEdge(id[i][j - 1], id[i][j], read());
for (int i = 1; i <= n + 1; ++i)
for (int j = 1; j <= n; ++j)
solver.AddEdge(id[i - 1][j], id[i][j], read());
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n + 1; ++j)
solver.AddEdge(id[i][j], id[i][j - 1], read());
solver.dijkstra(st);
printf("%d\n", solver.dist[en]);
return 0;
}