您的位置:首页 > 理论基础 > 计算机网络

POJ1087 A Plug for UNIX(网络流,最大流,EK算法)

2018-01-08 16:12 429 查看

Description

You are in charge of setting up the press room for the inaugural

meeting of the United Nations Internet eXecutive (UNIX), which has an

international mandate to make the free flow of information and ideas

on the Internet as cumbersome and bureaucratic as possible. Since the

room was designed to accommodate reporters and journalists from around

the world, it is equipped with electrical receptacles to suit the

different shapes of plugs and voltages used by appliances in all of

the countries that existed when the room was built. Unfortunately, the

room was built many years ago when reporters used very few electric

and electronic devices and is equipped with only one receptacle of

each type. These days, like everyone else, reporters require many such

devices to do their jobs: laptops, cell phones, tape recorders,

pagers, coffee pots, microwave ovens, blow dryers, curling irons,

tooth brushes, etc. Naturally, many of these devices can operate on

batteries, but since the meeting is likely to be long and tedious, you

want to be able to plug in as many as you can. Before the meeting

begins, you gather up all the devices that the reporters would like to

use, and attempt to set them up. You notice that some of the devices

use plugs for which there is no receptacle. You wonder if these

devices are from countries that didn’t exist when the room was built.

For some receptacles, there are several devices that use the

corresponding plug. For other receptacles, there are no devices that

use the corresponding plug. In order to try to solve the problem you

visit a nearby parts supply store. The store sells adapters that allow

one type of plug to be used in a different type of outlet. Moreover,

adapters are allowed to be plugged into other adapters. The store does

not have adapters for all possible combinations of plugs and

receptacles, but there is essentially an unlimited supply of the ones

they do have.

Input

The input will consist of one case. The first line contains a single

positive integer n (1 <= n <= 100) indicating the number of

receptacles in the room. The next n lines list the receptacle types

found in the room. Each receptacle type consists of a string of at

most 24 alphanumeric characters. The next line contains a single

positive integer m (1 <= m <= 100) indicating the number of devices

you would like to plug in. Each of the next m lines lists the name of

a device followed by the type of plug it uses (which is identical to

the type of receptacle it requires). A device name is a string of at

most 24 alphanumeric characters. No two devices will have exactly the

same name. The plug type is separated from the device name by a space.

The next line contains a single positive integer k (1 <= k <= 100)

indicati
4000
ng the number of different varieties of adapters that are

available. Each of the next k lines describes a variety of adapter,

giving the type of receptacle provided by the adapter, followed by a

space, followed by the type of plug.

Output

A line containing a single non-negative integer indicating the

smallest number of devices that cannot be plugged in.

Sample Input

4
A
B
C
D
5
laptop B
phone C
pager B
clock B
comb X
3
B X
X A
X D


Sample Output

1


思路

先说题意,一个人要去住宾馆,他带了很多用电器,但是这些用电器的充电器插头有各种各样的型号,宾馆里面有插座,也有很多型号,但是可能出现用电器的插头找不到与之匹配的插座的情况,宾馆里面还提供了很多不同种类的转换器(数量无限),可以将用电器的插头转换成另一种型号的插头。宾馆提供的插座总数一定,求出有多少个用电器无法插在插座上

以样例来解释:

4(四个插座,型号分别为A,B,C,D)
A
B
C
D
5 (五个用电器)
laptop B (laptop所需要的插座是B)
phone C (phone所需要的插座是C)
pager B (同上)
clock B (同上)
comb X (同上)
3 (三个转换器)
B X (可以将B插头转换为X插头)
X A (可以将X插头转换为A插头)
X D (可以将X插头转换为D插头)


我们考虑一下如何建图,我们需要一个超级源点超级汇点

把每一个源点和每一个用电器连接,容量为1
把宾馆本身提供的插座和汇点连接,容量为1
把用电器和它所对应的插头连接,容量为1
把转换器的转换前的插头和转换后的插头相连,容量为
inf
,因为无限提供转换器

这样图就建好了,然后求出最大流,再用用电器的总数减去最大流就是答案

注意,用电器,插座都是以字符串的形式给出,为了方便建图,可以用map来记录标号

代码

#include <cstdio>
#include <cstring>
#include <cctype>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const int N=600+20;
int g

,pre
;
bool vis
;
int st,ed,p;
bool bfs(int s,int t)
{
mem(pre,-1);
mem(vis,false);
queue<int>q;
vis[s]=true;
q.push(s);
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i=st; i<=ed; i++)
{
if(!vis[i]&&g[now][i]>0)
{
vis[i]=true;
pre[i]=now;
if(i==t)
return true;
q.push(i);
}
}
}
return false;
}
int EK(int s,int t)
{
int v,w,d,maxflow=0;
while(bfs(s,t))
{
v=t;
d=inf;
while(v!=s)
{
w=pre[v];
d=min(d,g[w][v]);
v=w;
}
maxflow+=d;
v=t;
while(v!=s)
{
w=pre[v];
g[w][v]-=d;
g[v][w]+=d;
v=w;
}
}
return maxflow;
}
map<string,int>mp;
int main()
{
string s1,s2;
int n,m,k;
while(cin>>n)
{
mem(g,0);
mp.clear();
int cnt=1;
for(int i=1; i<=n; i++)
{
cin>>s1;
mp[s1]=cnt++;
g[mp[s1]][N-1]=1;//从源点建立一条到插座的边
}
cin>>m;
for(int i=1; i<=m; i++)
{
cin>>s1>>s2;
mp[s1]=cnt++;
if(mp[s2]==0)
mp[s2]=cnt++;
g[mp[s1]][mp[s2]]=1;
g[0][mp[s1]]=1;
}
st=0;
ed=N-1;
cin>>k;
for(int i=1; i<=k; i++)
{
cin>>s1>>s2;
g[mp[s1]][mp[s2]]=inf;
}
cout<<m-EK(st,ed)<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: