usaco 5.4 Telecowmunication(最小割点集)

Telecowmunication

Farmer John's cows like to keep in touch via email so they have created a network of cowputers so that they can intercowmunicate. These machines route email so that if there exists a sequence of c cowputers a1, a2, ..., a(c) such that a1 is connected to a2, a2 is connected to a3, and so on then a1 and a(c) can send email to one another.

Unfortunately, a cow will occasionally step on a cowputer or Farmer John will drive over it, and the machine will stop working. This means that the cowputer can no longer route email, so connections to and from that cowputer are no longer usable.

Two cows are pondering the minimum number of these accidents that can occur before they can no longer use their two favorite cowputers to send email to each other. Write a program to calculate this minimal value for them, and to calculate a set of machines that corresponds to this minimum.

For example the network:

               1*
              /  
             3 - 2*
shows 3 cowputers connected with 2 lines. We want to send messages between 1 with 2. Direct lines connect 1-3 and 2-3. If cowputer 3 is down, them there is no way to get a message from 1 to 2.

PROGRAM NAME: telecow

INPUT FORMAT

Line 1Four space-separated integers: N, M, c1, and c2. N is the number of computers (1 <= N <= 100), which are numbered 1..N. M is the number of connections between pairs of cowputers (1 <= M <= 600). The last two numbers, c1 and c2, are the id numbers of the cowputers that the questioning cows are using. Each connection is unique and bidirectional (if c1 is connected to c2, then c2 is connected to c1). There can be at most one wire between any two given cowputers. Computer c1 and c2 will not have a direction connection.
Lines 2..M+1The subsequent M lines contain pairs of cowputers id numbers that have connections between them.

SAMPLE INPUT (file telecow.in)

3 2 1 2
1 3
2 3

OUTPUT FORMAT

Generate two lines of output. The first line is the minimum number of cowputers that can be down before terminals c1 & c2 are no longer connected. The second line is a minimal-length sorted list of cowputers that will cause c1 & c2 to no longer be connected. Note that neither c1 nor c2 can go down. In case of ties, the program should output the set of computers that, if interpreted as a base N number, is the smallest one.

SAMPLE OUTPUT (file telecow.out)

1
3

题目:给你一个网络,和两台电脑的编号,求去掉最少的电脑,使这两台电脑不能连接。。。

分析:最小割问题,把每台电脑分为两个点,容量为1,原来的电路不变,容量为无穷,比如原来为( i,j )   现在变成两条边( i' ,j )  (j' , i)

然后最大流求之,对于第二个问,用那个退流定理,去掉这条边,新的最大流等于原最大流-这条边的容量,说明这是一条割边。。。

从小到大枚举,如果是割边就输出,并从图中删除。。。

PS:usaco 做到这里有点被卡住了T_T,居然插头DP也出现了= =

代码:

/*
ID: 15114582
PROG: telecow
LANG: C++
*/
#include<cstdio>
#include<iostream>
using namespace std;
const int mm=66666;
const int mn=222;
const int oo=1e9;
int node,src,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];
void prepare(int _node,int _src,int _dest)
{
    node=_node,src=_src,dest=_dest;
    for(int i=0;i<node;++i)head[i]=-1;
    edge=0;
}
void addedge(int u,int v,int c)
{
    ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;
    ver[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge++;
}
bool Dinic_bfs()
{
    int i,u,v,l,r=0;
    for(i=0;i<node;++i)dis[i]=-1;
    dis[q[r++]=src]=0;
    for(l=0;l<r;++l)
        for(i=head[u=q[l]];i>=0;i=next[i])
            if(flow[i]&&dis[v=ver[i]]<0)
            {
                dis[q[r++]=v]=dis[u]+1;
                if(v==dest)return 1;
            }
    return 0;
}
int Dinic_dfs(int u,int exp)
{
    if(u==dest)return exp;
    for(int &i=work[u],v,tmp;i>=0;i=next[i])
        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
        {
            flow[i]-=tmp;
            flow[i^1]+=tmp;
            return tmp;
        }
    return 0;
}
int Dinic_flow()
{
    int i,delta,ret=0;
    while(Dinic_bfs())
    {
        for(i=0;i<node;++i)work[i]=head[i];
        while(delta=Dinic_dfs(src,oo))ret+=delta;
    }
    return ret;
}
int main()
{
    freopen("telecow.in","r",stdin);
    freopen("telecow.out","w",stdout);
    int i,j,n,m,s,t,ans;
    while(~scanf("%d%d%d%d",&n,&m,&s,&t))
    {
        prepare(n+n+1,n+s,t);
        for(i=1;i<=n;++i)
            addedge(i,i+n,1);
        while(m--)
        {
            scanf("%d%d",&i,&j);
            addedge(n+i,j,oo);
            addedge(n+j,i,oo);
        }
        ans=Dinic_flow();
        printf("%d\n",ans);
        for(s=i=0;i<n+n;i+=2)
        {
            flow[i]=flow[i^1]=0;
            for(j=0;j<edge;j+=2)
                flow[j]+=flow[j^1],flow[j^1]=0;
            if(Dinic_flow()==ans-1)
            {
                --ans;
                if(s++)printf(" ");
                printf("%d",i/2+1);
            }
            else flow[i]=1;
        }
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值