• 题意
    • 有n头牛,F种零食,D种饮料(零食饮料每种仅一个)
    • 每头牛有一个吃喝清单,非清单上的零食饮料不吃
    • 问最多有多少头牛能吃上一种零食+一种饮料的豪华套餐
  • 题解
    • 一开始以为是清单上都要满足,想半天想不出来
    • 但是看清后发现只要1+1即可
    • 那么直接将源点连向饮料,流量为1
    • 将零食连向汇点,流量为1
    • 再将饮料连向对应的牛
    • 将牛连向对应的零食,流量为1
    • 最后将牛拆成两个点,中间限流为1,表示一头牛只能吃一份
    • 零食饮料顺序可反
  • 代码
    • #include<cstdio>
      #include<cstring>
      #include<algorithm>
      #include<queue>
      #include<iostream>
      using namespace std;
      #define rep(i,a,n) for(int i=a;i<=n;++i)
      #define per(i,a,n) for(int i=n;i>=a;--i)
      typedef long long ll;
      typedef unsigned long long ull;
      const int inf=1<<29,N=10010,M=300010;
      int head[N],ver[N],edge[N],Next[N],d[N];
      int n,p,s,t,tot,maxflow;
      queue<int>q;
      void add(int x,int y,int z) {
          ver[++tot]=y;
          edge[tot]=z;
          Next[tot]=head[x];
          head[x]=tot;
          ver[++tot]=x;
          edge[tot]=0;
          Next[tot]=head[y];
          head[y]=tot;
      }
      bool bfs() { //在残量网络上构造分层图
          memset(d,0,sizeof(d));
          while(q.size())q.pop();
          q.push(s);
          d[s]=1;
          while(q.size()) {
              int x=q.front();
              q.pop();
              for(int i=head[x]; i; i=Next[i])
                  if(edge[i]&&!d[ver[i]]) {
                      q.push(ver[i]);
                      d[ver[i]]=d[x]+1;
                      if(ver[i]==t)return 1;
                  }
          }
          return 0;
      }
      int dinic(int x,int flow) { //在当前分层图上增广
          if(x==t)return flow;
          int rest=flow,k;
          for(int i=head[x]; i; i=Next[i])
              if(edge[i]&&d[ver[i]]==d[x]+1) {
                  k=dinic(ver[i],min(rest,edge[i]));
                  if(!k)d[ver[i]]=0;
                  edge[i]-=k;
                  edge[i^1]+=k;
                  rest-=k;
              }
          return flow-rest;
      }
      int main() {
      	int F,D; 
          while(scanf("%d%d%d", &n,&F,&D)!=EOF) {
              tot=1;
              memset(head,0,sizeof(head));
              s=0, t=n*2+F+D+1;
              rep(i,1,F) add(s,i,1);
      		rep(i,1,D) add(F+n*2+i,t,1);
      		rep(i,1,n) add(F+i,F+n+i,1);
      		rep(i,1,n){
      			int t1,t2,f,d;
      			scanf("%d%d", &t1,&t2);
      			rep(j,1,t1){
      				scanf("%d", &f);
      				add(f,F+i,1);
      			}
      			rep(j,1,t2){
      				scanf("%d", &d);
      				add(F+n+i,F+n*2+d,1);
      			}
      		}
      		maxflow=0;
              int flow=0;
              while(bfs())
                  while(flow=dinic(s,inf))maxflow+=flow;
              printf("%d\n", maxflow);
          }
          return 0;
      }

发表评论

邮箱地址不会被公开。 必填项已用*标注