UNIX的插头问题
UNIX的插头问题
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
你负责为联合国互联网执行组织(UNIX)的周年会议布置会议室。该组织的主旨是使互联网上的信息和思想的自由交流变得尽可能笨重和官僚(^_^)。
因为会议室被审计为招待来自世界各地的记者的场所,它装备了一些电气插座以匹配各个国家使用的电器的不同插头形状和电压。当然,这些插座的规格是以这个会议室建成时世界各国的规格作为标准的。不幸的是,由于这座会议室年代久远,它建成时,记者还只是使用很少量的电子和电气设备,所以它对每种类型只配备了一个插座。今天,记者像其他人一样,需要很多设备才能工作:掌上型计算器,手提电话,录音机,寻呼机,电咖啡壶,微波炉,电吹风,电熨斗,电动牙刷,等等。自然,这些设备当中有许多可以靠电池驱动的,但是看起来这个会议将会冗长乏味,所以还是希望这些设备尽可能从插座供电。
在会议开始前,你将记者所有可能使用的设备集中起来,尝试将它们接到插座上。你注意到有些设备的插头没有相应的插座。你怀疑这些设备来自一些在这座会议室建成时还不存在的国家。对某些插座,也许有许多设备都是用对应的插头;而对另一些插座,也许没有任何设备使用对应的插头。 为了解决这个问题,你走到附近一家五金店气商店。这家商店出售一些转接头,可以将一种插头转换成另一种插头。一个转接头还可以接到另一个转接头上。并非所有插座和插头的组合都有相应的转接头,但是对每种出售的转接头,商店都有足够的存货。
因为会议室被审计为招待来自世界各地的记者的场所,它装备了一些电气插座以匹配各个国家使用的电器的不同插头形状和电压。当然,这些插座的规格是以这个会议室建成时世界各国的规格作为标准的。不幸的是,由于这座会议室年代久远,它建成时,记者还只是使用很少量的电子和电气设备,所以它对每种类型只配备了一个插座。今天,记者像其他人一样,需要很多设备才能工作:掌上型计算器,手提电话,录音机,寻呼机,电咖啡壶,微波炉,电吹风,电熨斗,电动牙刷,等等。自然,这些设备当中有许多可以靠电池驱动的,但是看起来这个会议将会冗长乏味,所以还是希望这些设备尽可能从插座供电。
在会议开始前,你将记者所有可能使用的设备集中起来,尝试将它们接到插座上。你注意到有些设备的插头没有相应的插座。你怀疑这些设备来自一些在这座会议室建成时还不存在的国家。对某些插座,也许有许多设备都是用对应的插头;而对另一些插座,也许没有任何设备使用对应的插头。 为了解决这个问题,你走到附近一家五金店气商店。这家商店出售一些转接头,可以将一种插头转换成另一种插头。一个转接头还可以接到另一个转接头上。并非所有插座和插头的组合都有相应的转接头,但是对每种出售的转接头,商店都有足够的存货。
输入
输入数据有若干行。第1行是一个整数n(1<=n<=100),表示会议室的插座数。接下来的n行列出了能在会议室找到的插座,每种插座的名称是由字母和数字组成的字符串,长度不超过24个字符。接着一行是一个整数m(1<=m<=100),表示你要连接的插头数。再接下来的m行列出了设备的名称和它使用的插头(与相应插座的名称相同)。两者用一个空格分隔。每种设备的名称也是字母和数字组成的字符串,长度不超过24个字符。没有两个设备的名称完全相同。接着一行是一个整数k(1<=k<=100),表示可用的转接头种类。接下来的k行每行描述了一种转接头,首先给出转接头提供的插座,接着一个空格,接下来是插头的类型。
输出
请将最少的无法连接的设备数输出。
示例输入
4 A B C D 5 laptop B phone C pager B clock B comb X 3 B X X A X D
示例输出
1
分析:二分最大匹配;n个插座作为一列,m个插头作为一列,形成二部图,接下来就是把可以对应的插座直接和插头连接或者间接和插头连接起来,对于每个插头或插座的名称离散化,然后对k个转换器建立单项边,然后搜索,可以搜到的点就可以间接连边;
程序:
#include"stdio.h" #include"string.h" #include"queue" #include"stack" #include"algorithm" #include"vector" #include"iostream" #include"math.h" #include"map" #include"stdlib.h" #define M 222 #define inf 100000000 using namespace std; int G[M][M],y[M],use[M],vis[M]; struct node { int v; node(int vv) { v=vv; } }; vector<node>edge[M]; int finde(int x,int m) { for(int i=1;i<=m;i++) { if(!use[i]&&G[x][i]) { use[i]=1; if(!y[i]||finde(y[i],m)) { y[i]=x; return 1; } } } return 0; } int slove(int n,int m) { memset(y,0,sizeof(y)); int ans=0; for(int i=1;i<=n;i++) { memset(use,0,sizeof(use)); ans+=finde(i,m); } return ans; } void dfs(int u) { vis[u]=1; for(int i=0;i<(int)edge[u].size();i++) { int v=edge[u][i].v; if(!vis[v]) dfs(v); } } int main() { int n,m,i,j,k; char ch[M][33],str[33],ch1[M][33],str1[33],str2[33]; while(scanf("%d",&n)!=-1) { map<string,int>mp; int num=0; for(i=1;i<=n;i++) { scanf("%s",ch[i]); if(!mp[ch[i]]) mp[ch[i]]=++num; } scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%s%s",str,ch1[i]); if(!mp[ch1[i]]) mp[ch1[i]]=++num; } scanf("%d",&k); for(i=1;i<=k;i++) { scanf("%s%s",str1,str2); edge[mp[str2]].push_back(node(mp[str1])); } memset(G,0,sizeof(G)); for(i=1;i<=n;i++) { int u=mp[ch[i]]; memset(vis,0,sizeof(vis)); dfs(u); for(j=1;j<=m;j++) { int v=mp[ch1[j]]; if(vis[v]) G[i][j]=1; } } int ans=slove(n,m); printf("%d\n",m-ans); /*for(i=1;i<=n;i++) { for(j=1;j<=m;j++) printf("%d-->%d:%d\n",i,j,G[i][j]); }*/ for(i=1;i<=num;i++) edge[i].clear(); } return 0; }