attackonworldtree hnoi 省选集训


网络流


#include<map>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>


const int MAXN = 55, NodeNum = (MAXN*5)<<1,INF = 2e8;
const int ni[2] = {-1,1};

int h,w,c,m,nw,nc,nm;
struct Edge{int v,cap,next;}edge[(NodeNum*MAXN)<<2] = {0},emp = {0};
int head[NodeNum], el , ind ,start , end;
bool hash[MAXN];int dep[NodeNum];
struct TwoNode{int in,out;}hh[MAXN],ww[MAXN],cc[MAXN],mm[MAXN],nnw,nnc,nnm;

void newedge(int u,int v,int cap)
{
    ++el; edge[el].v = v;
    edge[el].cap = cap;
    edge[el].next = head[u];
    head[u] = el;
}
void newone(TwoNode &x,int flow)
{
    x.in = ++ind,x.out = ++ind;
    head[x.in] = head[x.out] = 0;
    newedge(x.in,x.out,flow);
    newedge(x.out,x.in,0);
}

int line[NodeNum], f, r;
bool BFS()
{
    f = r = 0;
    memset(dep,0,sizeof(dep));

    line[r++] = start;
    dep[start] = 1;

    while(f!=r)
    {
        int now = line[f++];
        for(int i = head[now]; i ; i = edge[i].next)
          if(edge[i].cap)
         {
            int p = edge[i].v;
            if(dep[p])continue;
            else
            {
                dep[p] = dep[now]+1;
                line[r++] = p; 
            }
         }
    }
    if(dep[end])return true;
    else   return false;
}
int dfs(int a,int flow)
{
    if(!flow || a == end)return flow;

    int ret = 0;
    for(int i = head[a]; i && flow; i = edge[i].next)
    {
        int p = edge[i].v;

        if(dep[p] != dep[a] + 1 || !edge[i].cap)continue;

        int ff = dfs(p,std::min(flow,edge[i].cap));

        edge[i].cap -= ff ;
        edge[i+ni[i&1]].cap += ff;
        flow -= ff, ret += ff;
    }
    return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("attackonworldtree.in","r",stdin);
    freopen("attackonworldtree.out","w",stdout);
#endif

    while(1)
    {
      int totflow = 0;

      ind = el = 0; 
      scanf("%d%d%d%d%d%d%d",&h,&w,&c,&m,&nw,&nc,&nm);
      if(h == -1)break;

      for(int i = 1; i <= h; i++)newone(hh[i],1);
      for(int i = 1; i <= w; i++)newone(ww[i],1);
      for(int i = 1; i <= c; i++)newone(cc[i],1);
      for(int i = 1; i <= m; i++)newone(mm[i],1);

      newone(nnw,nw);
      newone(nnc,nc);
      newone(nnm,nm);

      for(int i = 1; i <= w; i++)
      { 
       int len, ph;scanf("%d",&len);
        while(len--)
       {
         scanf("%d",&ph);
         newedge(hh[ph].out,ww[i].in,1);
         newedge(ww[i].in,hh[ph].out,0);
       }
      }
      for(int i = 1; i <= c; i++)
      { 
       int len, pw;scanf("%d",&len);
        while(len--)
       {
         scanf("%d",&pw);
         newedge(ww[pw].out,cc[i].in,1);
         newedge(cc[i].in,ww[pw].out,0);
       }
      }
      for(int i = 1; i <= m; i++)
      { 
       int len, pc;scanf("%d",&len);
        while(len--)
       {
         scanf("%d",&pc);
         newedge(cc[pc].out,mm[i].in,1);
         newedge(mm[i].in,cc[pc].out,0);
       }
      }
      start = ++ind;
      end = ++ind;
      head[start] = head[end] = 0;
      for(int i = 1 ;i <= h; i++)
      {
        newedge(start,hh[i].in,1);
        newedge(hh[i].in,start,0);
      }
      for(int i = 1;i <= m; i++)
      {
        newedge(mm[i].out,end,1);
        newedge(end,mm[i].out,0);
      }

      for(int i = 1; i <= h; i++)
      {
        newedge(hh[i].out,nnw.in,1);
        newedge(nnw.in,hh[i].out,0);
      }
      for(int i = 1; i <= c; i++)
      {
        newedge(nnw.out,cc[i].in,1);
        newedge(cc[i].in,nnw.out,0); 
      }


      for(int i = 1; i <= w; i++)
      {
        newedge(ww[i].out,nnc.in,1);
        newedge(nnc.in,ww[i].out,0);
      }
      for(int i = 1; i <= m; i++)
      {
        newedge(nnc.out,mm[i].in,1);
        newedge(mm[i].in,nnc.out,0); 
      }


      for(int i = 1; i <= c; i++)
      {
        newedge(cc[i].out,nnm.in,1);
        newedge(nnm.in,cc[i].out,0);
      }
      newedge(nnm.out,end,c);
      newedge(end,nnm.out,0);


      totflow = 0;  
      while(1)//dinic
      {
        if(BFS() == false)break;

//      memset(hash,false,sizeof(hash));
        totflow += dfs(start,INF);
      }
      printf("%d\n",totflow);
    }
#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值