poj 1087 A Plug for UNIX(最大流)

http://poj.org/problem?id=1087

题目大意:

会议室里有n1个插座,n2个电器,n3种适配器;

一种电器对应一种插座,适配器则可以用于转换;

求最好的情况下有多少电器不能适配。


思路:

1、各个电器各自为一个节点,建立一个源点且源点到电器的容量为1;

2、将室内已有的插座各自为一个节点,建立一个汇点且各个插座到汇点的容量为1;

3、电器节点到插座节点的容量为1;

4、适配器转换的两种插座之间的容量为无穷大;


#pragma warning (disable:4786)
#include<iostream>
#include<string>
#include<map>
using namespace std;

const int inf=1<<30;
const int MAX=601;

int s,t;
int n;
int cap[MAX][MAX];

map <string,int> Map;

int maxflow()
{
	int pre[MAX];
	int queue[MAX];
	int head;
	int tail;

	int min_flow;
	int max_flow=0;
	int x,y;

	while(true)
	{
		memset(pre,-1,sizeof(pre));

		for(queue[head=tail=0]=s;head<=tail;head++)
		{
			x=queue[head];
			for(int i=1;i<=n;i++)
			{
			//	cout<<"x="<<x<<" i="<<i<<' '<<cap[x][i]<<endl;
				if(cap[x][i]>0 && pre[i]==-1)
				{
					pre[i]=x;
					queue[++tail]=i;
				}
				if(pre[t]!=-1)
					break;
			}	
		}
		if(pre[t]==-1)
			break;

		min_flow=inf;

		for(x=pre[y=t];y!=s;)
		{
			if(cap[x][y]<min_flow)
				min_flow=cap[x][y];
			y=x;
			x=pre[y];
		}
		

		for(x=pre[y=t];y!=s;)
		{
			cap[x][y] -= min_flow;
			cap[y][x] += min_flow;
			y=x;
			x=pre[y];
		}

		max_flow += min_flow;
	}
	return max_flow;
}

int main(int i,int j,int k)
{
	int n1,n2,n3;
	char str1[25],str2[25];
	
	while(~scanf("%d",&n1))
	{	
		memset(cap,0,sizeof(cap));
		s=1;
		t=2;
		int num=2;
		
		for(i=1;i<=n1;i++)
		{
			scanf("%s",str1);
			Map[str1]=++num;
			cap[num][t]=1;
		}

		scanf("%d",&n2);
		for(j=1;j<=n2;j++)
		{
			scanf("%s %s",str1,str2);
			Map[str1]=++num;
			cap[s][num]=1;

			if(!Map.count(str2))
			{
				Map[str2]=++num;
			}
			 cap[Map[str1]][Map[str2]]=1;
		}

		scanf("%d",&n3);
		for(k=1;k<=n3;k++)
		{
			scanf("%s %s",str1,str2);
			if(!Map.count(str1))
			{
				Map[str1]=++num;
			}
			if(!Map.count(str2))
			{
				Map[str2]=++num;
			}
			cap[Map[str1]][Map[str2]]=inf;
		}
		n=num;

		printf("%d\n",n2-maxflow());

	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值