P1345奶牛的电信(最小割)

题目描述

农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流。这些机器用如下的方式发送电邮:如果存在一个由 cc 台电脑组成的序列a_1,a_2,\cdots ,a_ca1,a2,,ac,且 a_1a1 与 a_2a2 相连,a_2a2 与 a_3a3 相连,等等。那么电脑 a_1a1 和 a_cac 就可以互发电邮。

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

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

以如下网络为例:

   1*
  /
 3 - 2*

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

输入格式

第一行:四个由空格分隔的整数:N,M,c_1,c_2N,M,c1,c2NN 是电脑总数,电脑由 11 到 NN 编号。MM 是电脑之间连接的总数。后面的两个整数 c_1c1 和 c_2c2 是上述两头奶牛使用的电脑编号。连接没有重复且均为双向的(即如果 c_1c1 与 c_2c2 相连,那么 c_2c2 与 c_1c1 也相连)。两台电脑之间至多有一条连接。电脑 c_1c1 和 c_2c2 不会直接相连。

第 22 到 M+1M+1 行:接下来的 MM 行中,每行包含两台直接相连的电脑的编号。

输出格式

一行,一个整数,表示使电脑 c_1c1 和 c_2c2 不能互相通信需要坏掉的电脑数目的最小值。

 

题解:

就是给出一个无向图,询问最少删掉几个点,使得c1和c2不连通。

把每个点拆成两个点,简称上点和下点。对于每条边,x的上点向y的下点连一条单向边,反之亦然。

最后把c1的上点作为源点,c2的下点作为汇点跑Dinic算法即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
const int inf=1e9;
int n,m;
struct node {
    int u,v,w,nxt;
}edge[maxn];
int head[maxn];
int tot;
void addedge (int u,int v,int w) {
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].nxt=head[u];
    head[u]=tot++;
    
} 

int dep[maxn];
int inq[maxn];
int cur[maxn];
int wjm;
int maxflow=0;
int s,t;
bool bfs () {
    for (int i=1;i<=2*n;i++) {
        cur[i]=head[i];
        dep[i]=inf;
        inq[i]=0;
    }
    dep[s]=0;
    queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int u=q.front();
        q.pop();
        inq[u]=0;
        for (int i=head[u];i!=-1;i=edge[i].nxt) {
            int v=edge[i].v;
            if (dep[v]>dep[u]+1&&edge[i].w) {
                dep[v]=dep[u]+1;
                if (inq[v]==0) {
                    q.push(v);
                    inq[v]=1;
                } 
            }
        }
    }
    if (dep[t]!=inf) return 1;
    return 0;
}
int dfs (int u,int flow) {
    int increase=0;
    if (u==t) {
        wjm=1;
        maxflow+=flow;
        return flow;
    }
    int used=0;
    for (int i=cur[u];i!=-1;i=edge[i].nxt) {
        cur[u]=i;
        int v=edge[i].v;
        if (edge[i].w&&dep[v]==dep[u]+1) {
            if (increase=dfs(v,min(flow-used,edge[i].w))) {
                used+=increase;
                edge[i].w-=increase;
                edge[i^1].w+=increase;
                if (used==flow) break;
            }
        }
    }
    return used;
}
int Dinic () {
    while (bfs()) {
        wjm=1;
        while (wjm==1) {
            wjm=0;
            dfs(s,inf);
        }
    }
    return maxflow;
}
int main () {
    scanf("%d%d%d%d",&n,&m,&s,&t);
    memset(head,-1,sizeof(head));
    //s=0,t=n+1;
       s+=n;
       for (int i=1;i<=n;i++) {
           addedge(i,i+n,1);
        addedge(i+n,i,0);    
    }
    for (int i=1;i<=m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        addedge(y+n,x,inf);
        addedge(x,y+n,0);
        addedge(x+n,y,inf);
        addedge(y,x+n,0);
    }
    printf("%d\n",Dinic());
}

 

posted @ 2020-07-16 15:17  zlc0405  阅读(119)  评论(0编辑  收藏  举报