[BeiJing2006]狼抓兔子
题意就是最小割.
然后这里我打了Dinic,然后2000ms-过了,用普通的sap则超时....
当然,此题还有一个平面图的解法,也是裸的.
然后就可以学习一下dij+heap的版本,再学习一下逼格比较高的最大最小定理...
棒棒哒~
- dinic虐暴sap啊
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define I register int
#define F(i, a, b) for (I i = a; i <= b; i ++)
#define mem(a, b) memset(a, b, sizeof a)
#define Get getchar()
const int N = 1e6 + 5, M = N * 6;
using namespace std;
int n, m, x, tot, S, T, dis[N], ans;
int tov[M], nex[M], len[M], las[N];
void R(I &x) {
char c = Get; x = 0; I t = 1;
for (; !isdigit(c); c = Get) t = (c == '-' ? - 1 : t);
for (; isdigit(c); x = (x << 3) + (x << 1) + c - '0', c = Get); x *= t;
}
int C(I x, I y) { return (x - 1) * m + y; }
void link(I x, I y, I L) {
tov[++ tot] = y, nex[tot] = las[x], las[x] = tot, len[tot] = L;
tov[++ tot] = x, nex[tot] = las[y], las[y] = tot, len[tot] = L;
}
bool bfs() {
mem(dis, 0), dis[S] = 1;
queue <int> Q; Q.push(S);
while (!Q.empty()) {
I k = Q.front(); Q.pop();
for (I x = las[k]; x; x = nex[x])
if (len[x] && !dis[tov[x]]) dis[tov[x]] = dis[k] + 1, Q.push(tov[x]);
}
return dis[T];
}
int dfs(I k, I flow) {
if (k == T) return flow;
I have = 0;
for (I x = las[k]; x; x = nex[x])
if (len[x] && dis[tov[x]] == dis[k] + 1) {
I now = dfs(tov[x], min(flow - have, len[x]));
have += now, len[x] -= now, len[x ^ 1] += now;
if (have == flow) return have;
}
if (!have) dis[k] = - 1;
return have;
}
int main() {
R(n), R(m), tot = 1, S = 1, T = n * m;
F(i, 1, n)
F(j, 1, m - 1) R(x), link(C(i, j), C(i, j + 1), x);
F(i, 1, n - 1)
F(j, 1, m) R(x), link(C(i, j), C(i + 1, j), x);
F(i, 1, n - 1)
F(j, 1, m - 1)
R(x), link(C(i, j), C(i + 1, j + 1), x);
while (bfs())
ans += dfs(S, 1e9);
printf("%d\n", ans);
}
然后转为平面图,用最短路搞搞...
实测:dijkstra+heap 2152ms ; spfa 3268ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define I register int
#define F(i, a, b) for (I i = a; i <= b; i ++)
#define mn(a, b) ((a) = (a) < (b) ? (a) : (b))
#define mem(a, b) memset(a, b, sizeof a)
#define Get getchar()
const int N = 2e6 + 10, M = 4 * N;
using namespace std;
int n, m, x, k, S, T, count, ans, dis[N]; bool vis[N];
int tov[M], nex[M], len[M], las[N], tot;
struct node {
int u, dis;
bool operator < (const node &a) const { return a.dis < dis; }
};
void R(I &x) {
char c = Get; x = 0; I t = 1;
for (; !isdigit(c); c = Get) t = (c == '-' ? - 1 : t);
for (; isdigit(c); x = (x << 3) + (x << 1) + c - '0', c = Get); x *= t;
}
void link(I x, I y, I L) {
tov[++ tot] = y, len[tot] = L, nex[tot] = las[x], las[x] = tot;
tov[++ tot] = x, len[tot] = L, nex[tot] = las[y], las[y] = tot;
}
void dijkstra() {
priority_queue<node> Q; mem(dis, 0x3f);
Q.push({S, 0}), dis[S] = 0, count = 1;
while (count --) {
k = Q.top().u; Q.pop();
if (vis[k]) continue; vis[k] = 1;
for (x = las[k]; x; x = nex[x])
if (dis[tov[x]] > dis[k] + len[x])
dis[tov[x]] = dis[k] + len[x], Q.push({tov[x], dis[tov[x]]}), count ++;
}
}
/*
void spfa() {
queue<int> Q; Q.push(S), mem(dis, 0x3f);
dis[S] = 0, count = 1, vis[S] = 1;
while (count --) {
k = Q.front(); Q.pop();
for (x = las[k]; x; x = nex[x])
if (dis[tov[x]] > dis[k] + len[x]) {
dis[tov[x]] = dis[k] + len[x];
if (!vis[tov[x]])
vis[tov[x]] = 1, Q.push(tov[x]), count ++;
}
vis[k] = 0;
}
}*/
int main() {
R(n), R(m), S = 0, T = ((n - 1) * (m - 1) << 1) + 1;
if (n == 1 || m == 1)
{
if (n > m) swap(n, m); I ans = 1e9;
F(i, 1, m - 1)
R(x), mn(ans, x);
printf("%d\n", ans); return 0;
}
F(i, 1, m - 1)
R(x), link(S, i, x);
F(i, 2, n - 1)
F(j, 1, m - 1) R(x), link((i - 2) * 2 * (m - 1) + (m - 1) + j, (i - 1) * 2 * (m - 1) + j, x);
F(i, 1, m - 1)
R(x), link((n - 2) * 2 * (m - 1) + (m - 1) + i, T, x);
F(i, 1, n - 1) {
R(x), link((i - 1) * 2 * (m - 1) + m, T, x);
F(j, 2, m - 1)
R(x), link((i - 1) * 2 * (m - 1) + j - 1, (i - 1) * 2 * (m - 1) + m + j - 1, x);
R(x), link((i - 1) * 2 * (m - 1) + m - 1, S, x);
}
F(i, 1, n - 1)
F(j, 1, m - 1)
R(x), link((i - 1) * 2 * (m - 1) + j, (i - 1) * 2 * (m - 1) + m - 1 + j, x);
dijkstra();
//spfa();
printf("%d", dis[T]);
}