BZOJ1458士兵占领 最大流的模板题

Posted TS_Hugh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1458士兵占领 最大流的模板题相关的知识,希望对你有一定的参考价值。

我们只要把他们可以有的限制用流量限制,再用两者关系限制一下就可以开心的跑了。

#include <cstdio>
#include <cstring>
#include <iostream>
#define r register
#define N 1005
using namespace std;
inline int read()
{
         r  int sum=0;
         r  char ch=getchar();
         while(ch<0||ch>9)ch=getchar();
         while(ch>=0&&ch<=9)
         {
                     sum=(sum<<1)+(sum<<3)+ch-0;
                     ch=getchar();
         }
         return sum;
}
int g[N][N];
struct VIA
{
        int to,next,w;
}c[N<<4];
int head[N<<1],t=1;
int n,m,k;
inline void add(int x,int y,int z)
{
        c[++t].to=y;
        c[t].next=head[x];
        head[x]=t;
        c[t].w=z;
}
int L[N],C[N],LL[N],CC[N],S,T;
int deep[N<<1],q[N<<1],top,tail;
inline bool bfs()
{
        memset(deep,0,sizeof(deep));
        q[1]=S;
        top=tail=1;
        deep[S]=1;
        while(top<=tail)
        {
            r  int x=q[top++];
            if(x==T)return 1;
            for(int i=head[x];i;i=c[i].next)
            if(c[i].w&&deep[c[i].to]==0)
            {
                deep[c[i].to]=deep[x]+1;
                q[++tail]=c[i].to;
            }
        }
        return 0;
}
inline int Min(int x,int y)
{
        return x<y?x:y;
}
int dfs(int x,int v)
{
         if(x==T||!v)return v;
         r  int ret=0;
         for(r  int i=head[x];i;i=c[i].next)
         if(c[i].w&&deep[c[i].to]==deep[x]+1)
         {
                 r  int f=Min(v,c[i].w);
                 r  int w=dfs(c[i].to,f);
                 v-=w;
                 ret+=w;
                 c[i].w-=w;
                 c[i^1].w+=w;
                 if(!v)break;
         }
         if(!ret)deep[x]=-1;
         return ret;
}
inline int dinic()
{
        r  int ans=0;
        while(bfs())ans+=dfs(S,0x7f7f7f7f);
        return ans;
}
int main()
{
      r  int ans=0;
        n=read(),m=read(),k=read();
    for(r  int i=1;i<=n;++i)L[i]=read(),LL[i]=m,ans+=L[i];
    for(r  int i=1;i<=m;++i)C[i]=read(),CC[i]=n,ans+=C[i];
    for(r  int i=1,x,y;i<=k;++i)x=read(),y=read(),g[x][y]=1,--LL[x],--CC[y];
    for(r  int i=1;i<=n;++i)
          if(L[i]>LL[i])
              {
                   printf("JIONG!\n");
                   return 0;
              }
    for(r  int i=1;i<=m;++i)
            if(C[i]>CC[i])
                {
                     printf("JIONG!\n");
                   return 0;
                }
    S=n+m+1,T=m+n+2;
    for(r  int i=1;i<=n;++i)
        for(r  int j=1;j<=m;++j)
            if(!g[i][j])
                add(i,j+n,1),add(j+n,i,0);
    for(r  int i=1;i<=n;++i)
        add(S,i,L[i]),add(i,S,0);
    for(r  int i=1;i<=m;++i)
        add(i+n,T,C[i]),add(T,n+i,0);
    ans-=dinic();
    printf("%d\n",ans);
}

 

以上是关于BZOJ1458士兵占领 最大流的模板题的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1458: 士兵占领 -- 最大流

BZOJ1458洛谷4311士兵占领(网络流)

BZOJ 1458 士兵占领

bzoj 1458 士兵占领

bzoj1458: 士兵占领 网络流

bzoj1458士兵占领