原题链接
继续写水题中
(DP)水题。
不过费用流解更灵活,可以解决(k)条路。
所以就写了个费用流。
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e4 + 10;
int fi[N], ne[N], da[N], di[N], co[N], la[N], q[N], cn[N], dis[N], l = 1, st, ed, n;
bool v[N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline void add(int x, int y, int z, int c)
{
di[++l] = y; da[l] = z; co[l] = c; ne[l] = fi[x]; fi[x] = l;
di[++l] = x; da[l] = 0; co[l] = -c; ne[l] = fi[y]; fi[y] = l;
}
inline int minn(int x, int y) { return x < y ? x : y; }
inline int calc(int x, int y) { return (x - 1) * n + y; }
bool spfa()
{
int i, x, y, head = 0, tail = 1;
memset(dis, 250, sizeof(dis));
dis[st] = 0;
q[1] = st;
while (head ^ tail)
{
x = q[++head];
v[x] = 0;
for (i = fi[x]; i; i = ne[i])
if (dis[y = di[i]] < dis[x] + co[i] && da[i] > 0)
{
dis[y] = dis[x] + co[i];
la[y] = x;
cn[y] = i;
if (!v[y])
{
q[++tail] = y;
v[y] = 1;
}
}
}
return dis[ed] > -1e7;
}
int main()
{
int i, j, x, y, z, o, k, s = 0;
n = re();
st = (o = n * n) << 1 | 1;
ed = st + 1;
while (1)
{
x = re(); y = re(); z = re();
if (!x && !y && !z)
break;
k = calc(x, y);
add(k, k + o, 1, z);
}
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
x = calc(i, j);
add(x, x + o, 1e9, 0);
if (i < n)
add(x + o, calc(i + 1, j), 1e9, 0);
if (j < n)
add(x + o, calc(i, j + 1), 1e9, 0);
}
add(st, 1, 2, 0);
add(o << 1, ed, 2, 0);
while (spfa())
{
int mi = 1e9;
for (i = ed; i ^ st; i = la[i])
mi = minn(mi, da[cn[i]]);
s += mi * dis[ed];
for (i = ed; i ^ st; i = la[i])
{
da[cn[i]] -= mi;
da[cn[i] ^ 1] += mi;
}
}
printf("%d", s);
return 0;
}