题意:
给n个插座和m个设备,每个设备只能接特定的插头,另外给k个适配器,每个适配器有两个参数:插座类型和插头类型,各个适配器间可互联且适配器使用不限。求不能接通的最小设备数。
思路:
对设备器可转换矩阵用floyd算法求闭包。然后对插座集和设备集进行二分图最大匹配。
代码:
#include <iostream>
#include <map>
#include <string>
using namespace std;
const int maxN=1024;
int M,v1,v2;
bool g[maxN][maxN];
bool vis[maxN];
int link[maxN];
int plug[maxN];
int notExist[maxN];
int adapter[maxN][maxN];
bool dfs(int x)
{
for(int y=1;y<=v2;++y)
if(g[x][y]&&!vis[y]){
vis[y]=true;
if(link[y]==0||dfs(link[y])){
link[y]=x;
return true;
}
}
return false;
}
void hungary()
{
for(int x=1;x<=v1;++x){
memset(vis,false,sizeof(vis));
if(dfs(x))
++M;
}
return ;
}
int main()
{
int i,j,n,m,k;
map<string,int> receptacle,device;
string a,b;
scanf("%d",&n);
for(i=1;i<=n;++i){
cin>>a;
receptacle[a]=i;
}
memset(notExist,0,sizeof(notExist));
scanf("%d",&m);
for(i=1;i<=m;++i){
cin>>a>>b;
device[a]=i;
if(receptacle[b]==0){
receptacle[b]=++n;
notExist[n]=1;
plug[i]=n;
}
else
plug[i]=receptacle[b];
}
memset(adapter,0,sizeof(adapter));
scanf("%d",&k);
for(i=1;i<=k;++i){
cin>>a>>b;
if(receptacle[a]==0){
receptacle[a]=++n;
notExist[n]=1;
}
if(receptacle[b]==0){
receptacle[b]=++n;
notExist[n]=1;
}
adapter[receptacle[a]][receptacle[b]]=1;
}
for(k=1;k<=n;++k)
adapter[k][k]=1;
for(k=1;k<=n;++k)
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
if(adapter[i][k]==1&&adapter[k][j]==1)
adapter[i][j]=1;
v1=n;
v2=m;
M=0;
memset(g,false,sizeof(g));
memset(link,0,sizeof(link));
for(i=1;i<=n;++i)
for(j=1;j<=m;++j){
int x=plug[j];
if(adapter[x][i]==1&¬Exist[i]==0)
g[i][j]=1;
}
hungary();
printf("%d",m-M);
}