poj1966 Cable TV Network 最大流

大意:任意的一个图,计算让图不连通所需删去的最小点数。

分析:最近在搞网络流,所以就往那个方面想,首先,拆点。原先节点所形成的那一段的容量为1,原先点与点之间的路径的容量为无穷大。让后枚举源汇点,计算所以这些情况所取得的最大流的最小值。一开始RE许久,后来改了一下,去掉了一维,只枚举汇点,因为若图被分割成多部分时,无论以图中哪一个点为源头,一定会存在一个最大流为0的汇点。(似乎, 还可以用最小割解释,本人若菜。。。)。


#include<stdio.h>
#include<string.h>
#define eps 1e8
#define LMT 54000
typedef struct
{
    int u,v,c,next;
}line;
line e[LMT],ef[LMT];
int lev[155],q[155],link[155],next[155];
int n,m,all,pal;
void insert(int u,int v,int c)
{
    e[all].u=u;
    e[all].v=v;
    e[all].c=c;
    e[all].next=next[u];
    next[u]=all++;
    e[all].u=v;
    e[all].v=u;
    e[all].next=next[v];
    e[all].c=0;
    next[v]=all++;
}
void copy()
{
    int i;
    for(i=0;i<all;i++)
      ef[i]=e[i];
}
int bfs(int s,int t)
{
    int head,tail,u,v,x;
    head=tail=0;
    memset(lev,0,sizeof(lev));
    q[tail++]=s;lev[s]=1;
    while(head<tail)
    {
        u=q[head++];
        for(x=next[u];x!=-1;x=ef[x].next)
        {
            v=ef[x].v;
            if(lev[v]==0&&ef[x].c>0)
            {
                lev[v]=lev[u]+1;
                q[tail++]=v;
            }
        }
    }
    return lev[t];
}
int dfs(int s,int t)
{
    int u,top=0,ret=0,i,x;
    q[top++]=s;
    while(top>0)
    {
        u=q[top-1];
        if(u==t)
        {
            int back,tiny=-1;
            for(i=top-1;i>0;i--)
            {
                x=link[q[i]];
                if(tiny==-1||ef[x].c<tiny)
                {
                    back=i;
                    tiny=ef[x].c;
                }
            }
            for(i=top-1;i>0;i--)
            {
                x=link[q[i]];
                ef[x].c-=tiny;
                ef[x^1].c+=tiny;
            }
             top=back;
             ret+=tiny;
             ret=ret>eps?eps:ret;
        }
        else
        {
            for(x=next[u];x!=-1;x=ef[x].next)
                if(ef[x].c>0&&lev[u]+1==lev[ef[x].v])
                {
                    q[top++]=ef[x].v;
                    link[ef[x].v]=x;
                    break;
                }
                if(x==-1)
                {
                    top--;
                    lev[u]=0;
                }
        }
    }
    return ret;
}
int dinic(int s,int t)
{
    int ret=0;
    while(bfs(s,t))
       ret+=dfs(s,t);
       if(ret>eps)ret=eps;
    return ret;
}
int main()
{
    int i,u,v,min,ret,j;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        getchar();
        if(n==1)printf("1\n");
        else if(n==0||m==0)printf("0\n");
        else
        {
            memset(next,-1,sizeof(next));
            all=0;
            for(i=0;i<n;i++)
               insert(i,i+n,1);
            while(m--)
            {
                scanf(" (%d,%d)",&u,&v);
                insert(u+n,v,eps);
                insert(v+n,u,eps);
            }
            min=eps;
            pal=all;
            for(i=1;i<n;i++)
              {
                  copy();
                  ret=dinic(n,i);
                  if(min>ret)min=ret;
              }
              if(min>=eps)min=n;
              printf("%d\n",min);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值