洛谷——P1345 [USACO5.4]奶牛的电信Telecowmunication

P1345 [USACO5.4]奶牛的电信Telecowmunication

题目描述

农夫约翰的奶牛们喜欢经过电邮保持联系,因而她们创建了一个奶牛电脑网络,以便互相交流。这些机器用以下的方式发送电邮:若是存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相连,a2与a3相连,等等,那么电脑a1和a(c)就能够互发电邮。ios

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

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

以以下网络为例:rest

1*code

/ 3 - 2*blog

这张图画的是有2条链接的3台电脑。咱们想要在电脑1和2之间传送信息。电脑1与三、2与3直接连通。若是电脑3坏了,电脑1与2便不能互发信息了。get

输入输出格式

输入格式:string

 

第一行 四个由空格分隔的整数:N,M,c1,c2.N是电脑总数(1<=N<=100),电脑由1到N编号。M是电脑之间链接的总数(1<=M<=600)。最后的两个整数c1和c2是上述两头奶牛使用的电脑编号。链接没有重复且均为双向的(即若是c1与c2相连,那么c2与c1也相连)。两台电脑之间至多有一条链接。电脑c1和c2不会直接相连。it

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

 

输出格式:

 

一个整数表示使电脑c1和c2不能互相通讯须要坏掉的电脑数目的最小值。

 

输入输出样例

输入样例#1:  复制
3 2 1 2
1 3
2 3
输出样例#1:  复制
1






最小割 看到这个题之后咱们首先想到的应该就是最小割了吧,可是最小割割的是边,这个题要求的是割点,怎么作?
拆点啊!咱们直接把每个点都才成两个点,两个点之间连一条流量为1的边,这样咱们就巧妙地把割点转化成了割边,
/*不难看出,这道题是求最小割点集的大小。

显然的是,对于一个点,它只能被删一次。~~废话~~

那么,对于每个点i,咱们都要复制它(设为i+n),而且从i到i+n连1的边(由于只能删一次)。(反向连0不要忘记)

add ( i, i+n, 1 ) ; add ( i+n, i, 0 ) ;而后怎么看待原图中原本就存在的边呢?它们只是有一个联通的做用,对于流量并无限制,因此明确一点:这些边加入网络中限制应该为无限大。

假设如今要从原图中添加一条从x到y的有向边(这道题是无向边,再依下面的方法添加一个y到x的就好了)到网络中去,对于点y来讲,这条边的加入不该该影响经过它的流量限制(就是前面连的那个1)
发生变化,因此前面那条y到y+n的边应该接在这条边的后面,因此这条边的终点连向网络中的y,相反的,这条边应该受到x的(前面连的1)限制。由于,假设x已经被删(x到x+n满流),那么这条边
再加不加都是没有变化的。因此,这条边在网络中的起点应该是x+n,这样才保证受到限制。
*/
 
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1000100
#define inf 9999999
using namespace std;
queue<int>q;
int n,m,s,e,x,y,tot=1,ans;
int to[N],cap[N],lev[N],cnt[N],head[N],nextt[N];
int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int add(int x,int y,int z)
{
    tot++;to[tot]=y;cap[tot]=z,nextt[tot]=head[x],head[x]=tot;
    tot++,to[tot]=x,cap[tot]=0,nextt[tot]=head[y],head[y]=tot;
}
int bfs()
{
    while(!q.empty()) q.pop();
    for(int i=1;i<=n*2;i++) 
    {
        lev[i]=-1;
        cnt[i]=head[i];
    }
    q.push(s),lev[s]=0;
    while(!q.empty())
    {
        x=q.front();q.pop();
        for(int i=head[x];i;i=nextt[i])
        {
            int t=to[i];
            if(cap[i]>0&&lev[t]==-1) 
            {
                lev[t]=lev[x]+1;    
                q.push(t);    
                if(t==e) return 1;    
            }
        }
    }
    return 0;
}
int dinic(int x,int flow)
{
    if(x==e) return flow;
    int delta,rest=0;
    for(int &i=cnt[x];i;i=nextt[i])
    {
        int t=to[i];
        if(cap[i]>0&&lev[t]==lev[x]+1)
        {
            delta=dinic(t,min(cap[i],flow-rest));
            if(delta)
            {
                cap[i]-=delta;
                cap[i^1]+=delta;
                rest+=delta;
                if(rest==flow) break;
            }
        }
    }
    if(rest!=flow) lev[x]=-1;
    return rest;
}
int main()
{
    n=read(),m=read(),s=read(),e=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read();
        add(x+n,y,inf),add(y+n,x,inf);
    }
    for(int i=1;i<=n;i++) add(i,i+n,1);          
    while(bfs()) 
     ans+=dinic(s+n,inf);
    printf("%d",ans);
    return  0;
} 
相关文章
相关标签/搜索