zoukankan      html  css  js  c++  java
  • 洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication

    题目描述

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

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

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

    以如下网络为例:

    1* / 3 - 2*

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

    输入输出格式

    输入格式:

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

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

    输出格式:

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

    输入输出样例

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



    一眼就能看出是最小割啊。。
    拆完点之后跑一边Dinic就行
    拆出的点之前连边权为1的边
    题目中给出的连边连INF的边
    关键是代码怎么写啊QWQ
    想了半天没想出来,

    看了一下学姐的发现了一种很巧妙的方法

    注意S和T的选择,

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int MAXN=801,INF=5*1e8+10;
    inline char nc()
    {
        static char buf[MAXN],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        char c=nc();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=nc();}
        return x*f;
    }
    int S=0,T=3001;
    struct node
    {
        int u,v,flow,nxt;
    }edge[MAXN*20];
    int head[MAXN],cur[MAXN],num=0;
    inline void add_edge(int x,int y,int z)
    {
        edge[num].u=x;
        edge[num].v=y;
        edge[num].flow=z;
        edge[num].nxt=head[x];
        head[x]=num++;
    }
    inline void AddEdge(int x,int y,int z) 
    {
        add_edge(x,y,z);
        add_edge(y,x,0);
    }int deep[MAXN];
    inline bool BFS()
    {
        memset(deep,0,sizeof(deep));
        deep[S]=1;
        queue<int>q;
        q.push(S);
        while(q.size()!=0)
        {
            int p=q.front();
            q.pop();
            for(int i=head[p];i!=-1;i=edge[i].nxt)
                if(!deep[edge[i].v]&&edge[i].flow)
                {
                    deep[edge[i].v]=deep[p]+1;q.push(edge[i].v);
                    if(edge[i].v==T) return 1;
                }
        }
        return deep[T];
    }
    int DFS(int now,int nowflow)
    {
        if(now==T||nowflow<=0)    return nowflow;
        int totflow=0;
        for(int &i=cur[now];i!=-1;i=edge[i].nxt) 
        {
            if(deep[edge[i].v]==deep[now]+1&&edge[i].flow)
            {
                int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
                edge[i].flow-=canflow;edge[i^1].flow+=canflow;
                totflow+=canflow;
                nowflow-=canflow;
                if(nowflow<=0) break;
            }
        }
        return totflow;
    }
    int Dinic()
    {
        int ans=0;
        while(BFS())
        {
            memcpy(cur,head,sizeof(head)); 
            ans+=DFS(S,INF);
        }
        return ans;
    }
    int main()
    {
        #ifdef WIN32
        freopen("a.in","r",stdin);
        #else
        #endif
        memset(head,-1,sizeof(head));
        int N=read(),M=read(),A=read(),B=read();
           for(int i=1;i<=N;i++) AddEdge(i+N,i,1);
        for(int i=1;i<=M;i++)
        {
            int x=read(),y=read();
            AddEdge(x,y+N,INF);
            AddEdge(y,x+N,INF);
        }
        S=A;T=B+N;
        printf("%d",Dinic());
        return  0;
    }



  • 相关阅读:
    【转】基于 Apache 在本地配置多个虚拟主机
    ubuntu linux下各种格式软件包的安装卸载
    钩子
    静态方法中不能使用 $this
    Redis Sentinel机制与用法说明【转】
    CI 分页类的使用
    MySQL压力测试
    简单配置.htaccess就可以实现的10个功能
    bzoj 3529 数表
    poj2773 Happy 2006
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/8409379.html
Copyright © 2011-2022 走看看