HDU 4292 Food(筑图+最大流)

HDU 4292 Food(建图+最大流)

请不要随便指点别人该怎么做、每个人的人生都应该自己掌握、你给不了别人一切、你也不懂别人的忧伤、

                                                                                          微笑不代表快乐、哭泣不一定悲伤

               不努力怎么让关心你的人幸福、不努力怎么让看不起你的人绝望、

                                                                                                                                    

                                                                                                                                                              我用生命在奋斗——lx_Zz

—————————————————————————————————————————————————————————————

—————————————————————————    华丽的分割线    ————————————————————————————

—————————————————————————————————————————————————————————————

110 给我再去相信的勇气、 125MS 2176K 3106B C++ 2014-05-07 16:56:58

2道2012年成都网络赛的最大流水题都切了、

感觉建模建的不怎么好、、、、

建立两个超级源点和汇点、将food和drink分别连在其中一个点上、然后建人拆点、因为每个能只能有1的流量、所以拆点限制流量、

然后将food和人、drink和人对应的连起来、就OK了


/* 题目: HDU 4292 Food */
/* 作者: lx_Zz         */
/* 时间: 2014.5.7      */
#include<cstdio>
#include<queue>
#include<vector>
#include<map>
#include<string>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define INF 0x7fffffff
#define LL __int64
#define N 1005
int f_num[N];
int d_num[N];
char str[N];

int k;
int level[N];
struct node
{
    int to,next,cost;
}edge[N*N];
int head[N];
int t_head[N];
int start,end;
void init()
{
    k=0;
    memset(head,-1,sizeof(head));
}
int bfs(int s,int t)//对顶点进行标号、找出层次图
{
    memset(level,0,sizeof(level));
    queue<int>q;
    q.push(s);
    level[s]=1;
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            int y=edge[i].to;
            if(!level[y]&&edge[i].cost>0)
            {
                level[y]=level[now]+1;
                q.push(y);
            }
        }
    }
    return level[t]!=0;//汇点是否在层次图中
}
int dfs(int s,int cp)//在层次图中寻找增广路进行增广
{
    int flow=0,temp;
    int t;
    if(s==end||cp==0)return cp;
    for(;t_head[s]+1;t_head[s]=edge[t_head[s]].next)
    {
        int y=edge[t_head[s]].to;
        if(level[s]+1==level[y])
        {
            temp=dfs(y,min(cp,edge[t_head[s]].cost));
            if(temp>0)
            {
                edge[t_head[s]].cost-=temp;
                edge[t_head[s]^1].cost+=temp;
                flow+=temp;
                cp-=temp;
                if(cp==0)break;
            }
        }
    }
    return flow;
}

int dinic()
{
    int ans=0,flow=0;
    while(bfs(start,end))//汇点不在层次图中、算法终止
    {
        for(int i=0;i<=end;i++)
            t_head[i]=head[i];
        ans+=dfs(start,INF);
    }
    return ans;
}
void add(int x,int y,int val)
{
    edge[k].to=y;
    edge[k].cost=val;
    edge[k].next=head[x];
    head[x]=k++;

    edge[k].to=x;
    edge[k].cost=0;
    edge[k].next=head[y];
    head[y]=k++;
}
int main()
{
    //freopen("C:\\Users\\终将我要华丽的逆袭\\Desktop\\lx_Zz_in.txt","r",stdin);
    //freopen("C:\\Users\\终将我要华丽的逆袭\\Desktop\\lx_Zz_out.txt","w",stdout);
    int n,f,d;
	while(scanf("%d%d%d",&n,&f,&d)!=EOF)
	{
		init();
		start=0;end=f+d+n*2+1;
		for(int i=1;i<=n;i++)
		{
			add(i*2-1,i*2,1);
		}
		for(int i=1;i<=f;i++)
			scanf("%d",&f_num[i]);
		for(int i=1;i<=d;i++)
			scanf("%d",&d_num[i]);
		for(int i=1;i<=f;i++)
		{
			add(start,n*2+i,f_num[i]);
		}
		for(int i=1;i<=d;i++)
		{
			add(n*2+f+i,end,d_num[i]);
		}
		for(int i=1;i<=n;i++)
		{
			scanf("%s",str+1);
			for(int j=1;j<=f;j++)
			{
				if(str[j]=='Y')
				{
					add(n*2+j,i*2-1,1);
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			scanf("%s",str+1);
			for(int j=1;j<=d;j++)
			{
				if(str[j]=='Y')
				{
					add(i*2,n*2+f+j,1);
				}
			}
		}
		printf("%d\n",dinic());
	}
    return 0;
}