洛谷1345 [USACO5.4]奶牛的電信Telecowmunication
阿新 • • 發佈:2018-11-05
原題連結
最小割點數轉換成最小割邊數的模板題(不過這資料好小)。
每個點拆成兩個點,連一條容量為\(1\)的邊,原圖的邊容量定為\(+\infty\),然後跑最大流即可。
這裡用的是\(Dinic\)。
#include<cstdio> #include<cstring> using namespace std; const int N = 220; const int M = 5e3; int fi[N], di[M], ne[M], da[M], de[N], q[N], cu[N], l = 1, st, ed; 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) { di[++l] = y; da[l] = z; ne[l] = fi[x]; fi[x] = l; di[++l] = x; da[l] = 0; ne[l] = fi[y]; fi[y] = l; } inline int minn(int x, int y){ return x < y ? x : y; } bool bfs() { int i, x, y, head = 0, tail = 1; memset(de, 0, sizeof(de)); q[1] = st; de[st] = 1; while (head ^ tail) { x = q[++head]; for (i = fi[x]; i; i = ne[i]) if (!de[y = di[i]] && da[i] > 0) { de[y] = de[x] + 1; if (!(y ^ ed)) return true; q[++tail] = y; } } return false; } int dfs(int x, int k) { if (!(x ^ ed)) return k; int mi, y; for (int &i = cu[x]; i; i = ne[i]) if (!(de[y = di[i]] ^ (de[x] + 1)) && da[i] > 0) { mi = dfs(y, minn(k, da[i])); if (mi > 0) { da[i] -= mi; da[i ^ 1] += mi; return mi; } } return 0; } int main() { int i, n, m, x, y, s = 0; n = re(); m = re(); st = re() + n; ed = re(); for (i = 1; i <= n; i++) add(i, i + n, 1); for (i = 1; i <= m; i++) { x = re(); y = re(); add(x + n, y, 1e9); add(y + n, x, 1e9); } while (bfs()) { for (i = 1; i <= (n << 1); i++) cu[i] = fi[i]; for (; (x = dfs(st, 1e9)) > 0; s += x); } printf("%d", s); return 0; }