[USACO5.4]奶牛的電信
阿新 • • 發佈:2018-11-10
傳送門:[USACO5.4]奶牛的電信
題目描述
農夫約翰的奶牛們喜歡通過電郵保持聯絡,於是她們建立了一個奶牛電腦網路,以便互相交流。這些機器用如下的方式傳送電郵:如果存在一個由c臺電腦組成的序列 ,且 與 相連, 與 相連,等等,那麼電腦 和 就可以互發電郵。
很不幸,有時候奶牛會不小心踩到電腦上,農夫約翰的車也可能碾過電腦,這臺倒黴的電腦就會壞掉。這意味著這臺電腦不能再發送電郵了,於是與這臺電腦相關的連線也就不可用了。
有兩頭奶牛就想:如果我們兩個不能互發電郵,至少需要壞掉多少臺電腦呢?請編寫一個程式為她們計算這個最小值。
以如下網路為例:
這張圖畫的是有 條連線的 臺電腦。我們想要在電腦 和 之間傳送資訊。電腦 與 、 與 直接連通。如果電腦 壞了,電腦 與 便不能互發資訊了。
分析
簡化題意,本題求的是無向圖的最小割點。
直接求是不可能的,可以考慮將割點轉化成割邊,然後直接求最大流。
對於如下的點
直接拆成這樣
然後跑最大流就行了
對於
,從
跑到
程式碼
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#define IL inline
using namespace std;
IL int read()
{
char c = getchar();
int sum = 0 ,k = 1;
for(;'0' > c || c > '9'; c = getchar())
if(c == '-') k = -1;
for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
return sum * k;
}
const int inf(0x3f3f3f3f);
int to[3505], nxt[3505], val[3505];
int cnt, last[505];
IL void add(int u, int v, int w)
{
to[++cnt] = v; nxt[cnt] = last[u]; val[cnt] = w; last[u] = cnt;
to[++cnt] = u; nxt[cnt] = last[v]; val[cnt] = 0; last[v] = cnt;
}
int S, T;
int dis[505], cur[505];
queue<int>Q;
IL int min_(int x, int y) { return x < y ? x : y; }
IL bool bfs()
{
memset(dis, 0, sizeof(dis));
for(; !Q.empty(); Q.pop());
Q.push(S); dis[S] = 1;
for(int u, v; !Q.empty();)
{
u = Q.front(); Q.pop();
for(int i = last[u]; i != -1; i = nxt[i])
if(val[i] && !dis[(v = to[i])])
{
dis[v] = dis[u] + 1;
if(v == T) return 1;
Q.push(v);
}
}
return 0;
}
IL int dfs(int u, int maxf)
{
if(!maxf || u == T) return maxf;
int flow = 0;
for(int &i = cur[u], v, f; i != -1; i = nxt[i])
if(val[i] && dis[(v = to[i])] == dis[u] + 1 && (f = dfs(v, min_(val[i], maxf))))
{
val[i] -= f;
val[i ^ 1] += f;
flow += f;
if(!(maxf -= f)) return flow;
}
return flow;
}
IL int max_flow()
{
int flow = 0;
//memcpy(cur, last, sizeof(last));
for(; bfs();)
{
memcpy(cur, last, sizeof(last));
flow += dfs(S, inf);
}
return flow;
}
int main()
{
int n = read(), m = read();
S = read() + n; T = read();
memset(last, -1, sizeof(last));
cnt = -1;
for(int i = 1; i <= n; ++i)
{
add(i, i + n, 1);
}
for(int i = 1, x, y; i <= m; ++i)
{
x = read(); y = read();
add(y + n, x, inf);
add(x + n, y, inf);
}
printf("%d\n", max_flow());
return 0;
}