SP300 CABLETV - Cable TV Network题解
裁剪自我的blog
题意:给出一个图,问最少删多少个点使得图不连通。
考虑转换为 0. 0. 0.
我们可以想到拆点:
把原图中点 i i i 去掉就先当于,在新图中把 i → i ′ i \rightarrow i' i→i′ 删掉了,这样 i ⇝ j i \rightsquigarrow j i⇝j 的路径就不复存在了。
我们用 0. 0. 0. 的套路,枚举 u , v u, v u,v 不连通。
构造好了,我们来看看怎么从原图转化到新构造的图,就是不存在 u ′ ⇝ v u' \rightsquigarrow v u′⇝v。
理解:
如图,例如 u ⇝ v u \rightsquigarrow v u⇝v 的路
路径为
相当于我们要阻塞这条增广路,但是我们发现如果这样增广的话,会将 u , v u, v u,v 两点删去(原图),所以我们选择 u ′ , v u', v u′,v。
但是还有一种情况,它饶了一圈然后删掉了 u → u ′ u \rightarrow u' u→u′, v → v ′ v \rightarrow v' v→v′ 呢?,这个时候这个路径上一定存在一条非 u → u ′ u \rightarrow u' u→u′, v → v ′ v \rightarrow v' v→v′ 的路径,那么我们选择删去这条边而不选择 u → u ′ u \rightarrow u' u→u′ 就行了(当然我们实际打代码时不需要管这条增广路到底删去了哪条边,只要知道它一定能构造出来就行了)。
除了这种情况没有非 u → u ′ u \rightarrow u' u→u′, v → v ′ v \rightarrow v' v→v′ 的路径 (即有 u ′ → v u' \rightarrow v u′→v)
这个时候增广路为 + ∞ +\infty +∞,我们就可以不用特判了。
所以其实最后代码非常简单,但是思维难度还是挺大的。(逻辑链条短,但是思维很非人……)
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); ++i)
#define per(i,j,k) for (int i = (j); i >= (k); --i)
template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
x = 0; T f = 1;
char ch = getchar ();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar ();
}
while (ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + ch - '0';
ch = getchar ();
}
x *= f;
}
template <typename T, typename... Args>
void read (T &x, Args&... args) {
read (x); read (args...);
}
char For_Print[25];
template <typename T>
void write (T x) {
if (x == 0) { putchar ('0'); return; }
if (x < 0) { putchar ('-'); x = -x; }
int poi = 0;
while (x) {
For_Print[++poi] = x % 10 + '0';
x /= 10;
}
while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
write (x); putchar (ch);
}
const LL Mod = 1e9 + 7;
const int Maxn = 2 * 1e3;
const int Maxm = 1e5;
const LL Inf = 0x3f3f3f3f;
void del (LL &x, LL y) { ((x -= y) < 0) && (x += Mod); }
void add (LL &x, LL y) { ((x += y) >= Mod) && (x -= Mod); }
struct edge {
int to[Maxm * 2 + 5], Next[Maxm * 2 + 5]; LL val[Maxm * 2 + 5];
int len, Head[Maxn + 5];
edge () { len = 1; memset (Head, 0, sizeof Head); }
void Init () {
len = 1;
memset (Head, 0, sizeof Head);
}
void plus (int x, int y, LL w) {
to[++len] = y;
Next[len] = Head[x];
val[len] = w;
Head[x] = len;
}
void add (int x, int y, LL w) {
plus (x, y, w); plus (y, x, 0);
}
}mp;
int s, t;
int hh, tt, q[Maxn + 5];
int depth[Maxn + 5], cur[Maxn + 5];
bool BFS () {
rep (i, 1, tt) depth[q[i]] = 0;
hh = 1; tt = 0; q[++tt] = s;
depth[s] = 1; cur[s] = mp.Head[s];
while (hh <= tt) {
int u = q[hh++];
for (int i = mp.Head[u]; i; i = mp.Next[i]) {
int v = mp.to[i]; LL w = mp.val[i];
if (w == 0) continue;
if (depth[v]) continue;
depth[v] = depth[u] + 1;
cur[v] = mp.Head[v];
q[++tt] = v;
if (v == t) return 1;
}
}
return 0;
}
LL DFS (int u, LL Up) {
if (u == t) return Up;
if (Up == 0) return 0;
LL flow = 0;
for (int i = cur[u]; i && Up != flow; i = mp.Next[i]) {
int v = mp.to[i]; LL w = mp.val[i];
cur[u] = i;
if (w == 0) continue;
if (depth[v] != depth[u] + 1) continue;
LL tmp = DFS (v, Min (Up - flow, w));
if (tmp == 0) depth[v] = -1;
flow += tmp; mp.val[i] -= tmp; mp.val[i ^ 1] += tmp;
}
return flow;
}
LL Dinic () {
LL flow = 0;
while (BFS ()) {
flow += DFS (s, Inf);
}
return flow;
}
int n, m;
int x[Maxn + 5], y[Maxn + 5];
int main () {
// freopen ("D:\\lihan\\1.in", "r", stdin);
// freopen ("D:\\lihan\\1.out", "w", stdout);
while (cin >> n >> m) {
rep (i, 1, m) read (x[i], y[i]), x[i]++, y[i]++;
LL ans = n;
rep (date_t, 2, n) {
mp.Init ();
s = 1 + n; t = date_t;
rep (i, 1, n) mp.add (i, i + n, 1);
rep (i, 1, m) {
mp.add (x[i] + n, y[i], 1);
mp.add (y[i] + n, x[i], 1);
}
ans = Min (ans, Dinic ());
}
if (ans == n - 1) {
print (n, '\n');
}
else {
print (ans, '\n');
}
}
return 0;
}