[USACO5.4]奶牛的电信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27121257/article/details/82963070

传送门:[USACO5.4]奶牛的电信


题目描述

农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流。这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列 a 1 , a 2 , . . . , a c a_1,a_2,...,a_c ,且 a 1 a_1 a 2 a_2 相连, a 2 a_2 a 3 a_3 相连,等等,那么电脑 a 1 a_1 a c a_c 就可以互发电邮。

很不幸,有时候奶牛会不小心踩到电脑上,农夫约翰的车也可能碾过电脑,这台倒霉的电脑就会坏掉。这意味着这台电脑不能再发送电邮了,于是与这台电脑相关的连接也就不可用了。

有两头奶牛就想:如果我们两个不能互发电邮,至少需要坏掉多少台电脑呢?请编写一个程序为她们计算这个最小值。

以如下网络为例:

1 / 3 2 1* / 3 - 2*

这张图画的是有 2 2 条连接的 3 3 台电脑。我们想要在电脑 1 1 2 2 之间传送信息。电脑 1 1 3 3 2 2 3 3 直接连通。如果电脑 3 3 坏了,电脑 1 1 2 2 便不能互发信息了。


分析

简化题意,本题求的是无向图的最小割点。
直接求是不可能的,可以考虑将割点转化成割边,然后直接求最大流。
对于如下的点

直接拆成这样
在这里插入图片描述
然后跑最大流就行了
对于 S , T S, T ,从 S 2 S2 跑到 T 1 T1


代码

#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;
}

猜你喜欢

转载自blog.csdn.net/qq_27121257/article/details/82963070