【JZOJ 4201】【BZOJ 4177】Mike的农场

description

这里写图片描述

Solution

很明显的最小割,
每一个点,向S连一条流量 ai 的边,向T连 bi 的边,
对于每个相互影响,把i,j连一条双向流量k的边,
额外的收入则新建一个点,如a=0,向S连一条b的边,并向集合S的每个点连流量无限边,a=1则反之,

Code

我加了当前弧优化还慢了?!
这里写图片描述

#include<cstdio>
#include<cstdlib> 
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
using namespace std;
typedef long long LL;
const int N=5500,maxlongint=1047483640;
int read(int &n)
{
    char ch=' ';int q=0,w=1;
    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
    if(ch=='-')w=-1,ch=getchar();
    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,m1,S,T;
LL ans;
int A[N*2],A1[N*2],B[100*N][3],B0=1;
int h[N*2],hv[N*2];
int min(int a,int b){return a>b?b:a;}
void link(int q,int w,int e,int e1)
{
    if(!A[q])A1[q]=B0+1;
    B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w,B[B0][2]=e;
    if(!A[w])A1[w]=B0+1;
    B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q,B[B0][2]=e1;
}
LL aug(int q,LL e)
{
    if(q==T)return e;
    LL mi=T+2;LL E=e;
    int i1=A1[q];
    efo(i,q)
    {
        if(B[i][2])
        {
            int w=B[i][1];
            if(h[q]==h[w]+1)
            {
                LL t=aug(w,min(e,B[i][2]));
                B[i][2]-=t;
                B[i^1][2]+=t;
                e-=t;
                if(h[S]>T+1||!e)
                {
                    B[A1[q]][0]=A[q];
                    A[q]=i;A1[q]=i1;B[A1[q]][0]=0;
                    return E-e;
                }
            }
            mi=min(mi,h[w]);
        }
        i1=i;
    }
    if(E==e)
    {
        if((--hv[h[q]])==0)h[S]=T+2;
        hv[h[q]=mi+1]++;
    }
    return E-e;
}
int main()
{
    freopen("work.in","r",stdin);
    freopen("work.out","w",stdout);
    int q,w,e;
    read(n),read(m1),read(m);
    S=0,T=n+m+1;ans=0;
    fo(i,1,n)read(q),link(S,i,q,0),ans+=q;
    fo(i,1,n)read(q),link(i,T,q,0),ans+=q;
    fo(i,1,m1)read(q),read(w),read(e),link(q,w,e,e);
    fo(i,1,m)
    {
        read(q),read(w),read(e);
        if(!q)continue;
        ans+=e;
        if(!w)link(S,n+i,e,0);else link(n+i,T,e,0);
        fo(j,1,q)
        {
            read(e);
            if(w)link(e,n+i,maxlongint,0);else link(n+i,e,maxlongint,0);
        }
    }
    hv[0]=T+1;
    while(h[S]<T+1)ans-=aug(S,maxlongint);
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值