BZOJ 大视野 1001 狼抓兔子

19 篇文章 0 订阅

最小割,双向边


#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct node
{
    int x,y,c,next,other;
}a[6110000]; int len,first[1110000];
int list[1110000],h[1110000];
int st,ed,head,tail,n,m;
 
void ins( int x,int y,int c )
{
    int k1,k2;
    k1=++len;
    k2=++len;
    a[k1].x=x; a[k1].y=y; a[k1].c=c;
    a[k2].x=y; a[k2].y=x; a[k2].c=c;
    a[k1].next = first[x]; first[x] = k1;
    a[k2].next = first[y]; first[y] = k2;
     
    a[k1].other = k2; 
    a[k2].other = k1;
}
bool bfs()
{
    memset( h,0,sizeof h );
    memset( list,0,sizeof list );
    h[st]=1; list[1]=st;
    head=tail=1;
    while( head<=tail )
    {
        int x=list[head];
        for( int k=first[x];k;k=a[k].next )
        {
            int y=a[k].y;
            if( !h[y] && a[k].c )
            {
                h[y] = h[x]+1;
                list[ ++tail ] = y;
            }
        }
        head++;
    }
    return h[ed]>0;
}
int dfs( int x,int flow )
{
    if( x==ed ) return flow;
    int delta=0,y,p;
    for( int k=first[x];k;k=a[k].next )
    {
        int y=a[k].y;
        if( h[y] == h[x]+1 && a[k].c && delta<flow )
        {
            p=dfs( y,min( flow-delta,a[k].c ) );
            delta+=p;
            a[k].c-=p; a[ a[k].other ].c+=p;
        }
    }
    if( delta == 0 )h[x] = 0;
    return delta;
}
 
int main()
{
    memset( first,0,sizeof first ); len = 0;
    int i,j,x,k,delta;
     
    scanf( "%d%d",&n,&m );
    st = 1; ed = n*m;
    for( i=1;i<=n;i++ )
        for( j=1;j<m;j++ )
        {
            scanf( "%d",&x );
            k = (i-1)*m+j;
            ins( k,k+1,x );
        }
    for( i=1;i<n;i++ )
        for( j=1;j<=m;j++ )
        {
            scanf("%d",&x);
            k = (i-1)*m+j;
            ins( k,k+m,x );
        }
    for( i=1;i<n;i++ )
        for( j=1;j<m;j++ )
        {
            scanf("%d",&x);
            k = (i-1)*m+j;
            ins( k,k+m+1,x );
        }
    k=0;
    while( bfs() )
    {
        while( delta=dfs( st,0x7fffffff ) ) k+=delta;
    }
    printf("%d\n",k);
     
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值