您的位置:首页 > 其它

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

2016-06-23 19:26 387 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: