Food (割点+网络流)

Food
/*
Food
HDU - 4292
https://cn.vjudge.net/problem/HDU-4292
题面:每个人有多个喜欢的食物和饮料,每个人只能挑一种食物和饮料,问最大能满足多少人
解法: 割点(吧人分成两部分,中间用边权为1的线连接,这样保证每个人只能挑一种食物和饮料)
      建图(原点-->食物-->人1-->人2-->饮料-->汇点)
      开始跑最大流
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1001000
#define ll long long
struct node{
  int v, w;
  int next;
}wedge[maxn<<1];
int whead[maxn];
int wcnt;
int dis[maxn];
int n,f,d;
int fx,dx;
int B,E;
void init(){
  memset(whead, -1, sizeof whead);
  wcnt = 0;
}
void add(int u,int v,int w){
  wedge[wcnt].w=w;
  wedge[wcnt].v=v;
  wedge[wcnt].next=whead[u];
  whead[u]=wcnt++;

  wedge[wcnt].w=0;
  wedge[wcnt].v=u;
  wedge[wcnt].next=whead[v];
  whead[v]=wcnt++;
}
bool bfs(int B,int E){
  memset(dis,-1,sizeof dis);
  queue<int> q;
  dis[B]=0;
  q.push(B);
  while(!q.empty()){
    int st=q.front();
    q.pop();
    for(int i=whead[st];~i;i=wedge[i].next){
      if(dis[wedge[i].v]==-1&&wedge[i].w>0){
        dis[wedge[i].v]=dis[st]+1;
        q .push(wedge[i].v);
      }
    }
  }
  return dis[E]!=-1;
}
int dfs(int u,int low)
{
    int flow;
    if(u==E)   return low;
    for(int i=whead[u];i!=-1;i=wedge[i].next)
    {
        if(wedge[i].w
        && (dis[wedge[i].v]==dis[u]+1)
        && (flow = dfs(wedge[i].v,min(low,wedge[i].w)))){
            wedge[i].w-=flow;
            wedge[i^1].w+=flow;
            return flow;
        }
    }
    dis[u]=-1;
    return 0;
}
void dinic(int B,int E){
  int ans=0;
  int t;
  while(bfs(B,E)){
    while(t=dfs(B,INF)) ans+=t;
  }
  printf("%d\n", ans);
}
int main(){
  while(~scanf("%d %d %d", &n, &f, &d)){
    init();
    B=0,E=800+1;
    for(int i=1;i<=f;i++){
      scanf("%d", &fx);
      add(0,i,fx);
    }
    for(int i=1;i<=d;i++){
      scanf("%d", &dx);
      add(600+i,E,dx);
    }
    char c[300];
    for(int i=1;i<=n;i++){
      scanf("%s", c+1);
      for(int j=1;j<=f;j++){
        if(c[j]=='Y'){
          add(j,200+i,1);
        }
      }
    }
    for(int i=1;i<=n;i++){
      scanf("%s", c+1);
      for(int j=1;j<=d;j++){
        if(c[j]=='Y'){
          add(400+i,600+j,1);
        }
      }
    }
    for(int i=1;i<=n;i++){
      add(i+200,i+2*200,1);
    }
    dinic(B,E);
  }
}
发布了70 篇原创文章 · 获赞 22 · 访问量 6505

猜你喜欢

转载自blog.csdn.net/weixin_44410512/article/details/100181304