HDU - 4292 Food 拆点最大流,这题怎么有点熟悉

题目链接

https://vjudge.net/problem/HDU-4292

题意

n个人,f食物,d饮品,每个人要么不吃不喝,要么有吃有喝,给定食物饮品数量,每个人对食物饮品的偏好,求最大满足多少人

思路

和前两天写的那个牛的那题一个思路,只不过因为食物饮料有数量,边权把1换成数量就行了。建图比较简单,写在代码注释里了,如果还是有点不懂可以看我这篇博客POJ - 3281

代码

#include<cstdio>
#include<iostream>
#include<iomanip>
#include<map>
#include<string>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib> 
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define endl "\n"
//#define int long long
using namespace std;
	typedef long long ll;
	const int inf=0x3f3f3f3f;
	const int maxn=1010;//200food + 200drink + 200*2people + s + t
	const int maxe=200010;//(200+200*200+200+200*200+200)*2

	int head[maxn],cnt;
	struct Edge{
    
    
		int v;
		int w;
		int next;
	}edge[maxe];

	int n,f,d,s,t;
	ll maxflow;
	int deep[maxn];
	int now[maxe];


	void init(){
    
    
		memset(head,-1,sizeof(head));
		cnt=0;
		maxflow=0; 
		return ;	
	}
	void add(int u,int v,int w){
    
    
		//cout<<u<<" "<<v<<" "<<w<<endl;
  		edge[cnt].v=v;
		edge[cnt].w=w;
		edge[cnt].next=head[u];
		head[u]=cnt++;
	}

	inline bool bfs(){
    
    
    	memset(deep,0x3f,sizeof(deep));
    	queue<int>q;
    	q.push(s);deep[s] = 0;now[s] = head[s];
    	while(q.size()){
    
    
        	int x = q.front();q.pop();
        	for(int i=head[x];i!=-1;i=edge[i].next){
    
    
        	    int y=edge[i].v;
         	    if(edge[i].w>0&&deep[y]==inf){
    
    
         	    	q.push(y);
        	        now[y]=head[y];
         	       	deep[y]=deep[x]+1;
        	        if(y==t)	return 1;
				}
        	}
    	}
    	return 0;
	}


	ll dfs(int x,int flow){
    
    
    	if(x==t)	return flow;
    	ll ans = 0,k,i;
    	for(i=now[x];i!=-1&&flow;i=edge[i].next){
    
    
        	now[x]=i;
        	int y=edge[i].v;
        	if(edge[i].w>0&&(deep[y]==deep[x]+1)){
    
    
        	    k=dfs(y,min(flow,edge[i].w));
         		if(!k)	deep[y]=inf;
            	edge[i].w-=k;
            	edge[i^1].w+=k;
            	ans+=k;
            	flow-=k;
        	}
    	}
    	return ans;
	}	

	void dinic(){
    
    
    	while(bfs())
    	    maxflow+=dfs(s,inf);
	}

	int main(){
    
    	
		IOS
		//一定注意多组输入 
		while(cin>>n>>f>>d){
    
    
			//s,t设成绝对标不到的两个数 
			s=999,t=s+1;
			init();
			//编号方便 
			int _fd=0,_dk=205,_pl=410,_pll=615;
			//s向食物连边,权为数量 
			for(int i=1;i<=f;i++){
    
    
				int ff;
				cin>>ff;
				add(s,i+_fd,ff);
				add(i+_fd,s,0);
			}
			//饮料向t连边,权为数量
			for(int i=1;i<=d;i++){
    
    
				int dd;
				cin>>dd;
				add(i+_dk,t,dd);
				add(t,i+_dk,0);
			}
			//食物向人in连边,权1 
			for(int i=1;i<=n;i++){
    
    
				char ch;
				for(int j=1;j<=f;j++){
    
    
					cin>>ch;
					if(ch=='Y'){
    
    
						add(j+_fd,i+_pl,1);
						add(i+_pl,j+_fd,0);
					}
				}
			}
			//人out向饮料连边,权1  
			for(int i=1;i<=n;i++){
    
    
				char ch;
				for(int j=1;j<=d;j++){
    
    
					cin>>ch;
					if(ch=='Y'){
    
    
						add(i+_pll,j+_dk,1);
						add(j+_dk,i+_pll,0);
					}
				}
			}
			//人in向人out连边,权1 
			for(int i=1;i<=n;i++){
    
    
				add(i+_pl,i+_pll,1);
				add(i+_pll,i+_pl,0);
			}
			dinic();
	    	cout<<maxflow<<endl;
		}
    	return 0;
	}	

猜你喜欢

转载自blog.csdn.net/TheSunspot/article/details/108344267
今日推荐