Solution
这样建图:对每一行每一列都建一个点,连向行内的荷叶。
那这道题就相当于删去最少的点使得源汇点不连通。
按这里一样建图就好了。
又忘记写当前弧优化了
#include <bits/stdc++.h>
using namespace std;
const int N = 233;
const int INF = 1 << 28;
struct edge {
int to, cap, next;
edge(int t = 0, int c = 0, int n = 0):to(t), next(n), cap(c) {}
};
edge G[N * N * 10];
int head[N * N], cur[N * N];
int Gcnt, n, m, S, T, clc, cnt, ans;
char mp[N][N];
int dis[N * N], vis[N * N];
int in[N][N], out[N][N];
int r[N], c[N];
queue<int> Q;
inline void AddEdge(int from, int to, int cap) {
G[++Gcnt] = edge(to, cap, head[from]); head[from] = Gcnt;
G[++Gcnt] = edge(from, 0, head[to]); head[to] = Gcnt;
}
inline bool bfs(int S, int T) {
dis[S] = 0; Q.push(S); vis[S] = ++clc;
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (int i = head[u]; i; i = G[i].next) {
edge &e = G[i];
if (e.cap && vis[e.to] != clc) {
dis[e.to] = dis[u] + 1;
vis[e.to] = clc; Q.push(e.to);
}
}
}
return vis[T] == clc;
}
inline int dfs(int u, int a) {
int flow = 0, f;
if (u == T || a == 0) return a;
for (int &i = cur[u]; i; i = G[i].next) {
edge &e = G[i];
if (e.cap && dis[e.to] == dis[u] + 1
&& (f = dfs(e.to, min(a, e.cap))) > 0) {
e.cap -= f; flow += f;
G[i ^ 1].cap += f; a -= f;
if (a == 0) break;
}
}
return flow;
}
inline int MaxFlow(int S, int T) {
int flow = 0;
while (bfs(S, T)) {
for (int i = 1; i <= cnt; i++) cur[i] = head[i];
flow += dfs(S, INF);
}
return flow;
}
int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
Gcnt = 1;
scanf("%d %d\n", &n, &m);
S = ++cnt; T = ++cnt;
for (int i = 1; i <= n; i++) {
scanf("%s", mp[i] + 1);
for (int j = 1; j <= m; j++)
if (mp[i][j] == 'o') {
in[i][j] = ++cnt;
out[i][j] = ++cnt;
}
}
for (int i = 1; i <= n; i++) r[i] = ++cnt;
for (int i = 1; i <= m; i++) c[i] = ++cnt;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (mp[i][j] == 'S') {
AddEdge(S, r[i], INF);
AddEdge(S, c[j], INF);
} else if (mp[i][j] == 'T') {
AddEdge(r[i], T, INF);
AddEdge(c[j], T, INF);
} else if (mp[i][j] == 'o') {
AddEdge(r[i], in[i][j], INF);
AddEdge(c[j], in[i][j], INF);
AddEdge(in[i][j], out[i][j], 1);
AddEdge(out[i][j], r[i], INF);
AddEdge(out[i][j], c[j], INF);
}
ans = MaxFlow(S, T);
if (ans > n * m) ans = -1;
cout << ans << endl;
return 0;
}
本文介绍了一种利用最小割算法解决特定路径问题的方法。通过建立一个包含源点和汇点的图,并对每行每列设置节点,连接行内的荷叶节点,问题转化为寻找最少的节点移除数量以断开源点与汇点的连接。文章提供了完整的C++代码实现,展示了如何通过最大流算法来计算最小割。
1万+

被折叠的 条评论
为什么被折叠?



