<转>poj 1087 A Plug for UNIX

PKU 1087 A Plug for UNIX

floyd+2分图最大匹配

题目非常冗长,大体意思就是说给出若干种类型的插头,(Ti (0<=i<n)),再给出若干物品(Oi (0<=i<m))
每个物品都只能插到固定类型的插头中,注意这里可能出现某个物品所对应的插头未在上面中给出的情况。
4
A
B
C
D
5
laptop B
phone C
pager B
clock B
comb X
3
B X
X A
X D接下来K行表示输入某些关系 (Ai,Bi)表示Ai,Bi之间可以转换.
Ai->Bi
接下来的问题就是问最少有几个物品无法插到他所对应的那个类型的插头中去
问题既是求最多能有几个插头被正确的插上
显然可以构造一个图论的模型,左边是点集Oi (0<=i<m) 表示物品
右边是插头Vi(0<=i<n)
这里就有一个问题了
由于数据中可能出现某些未出现过的插头,而这些未出现的插头可能可以由某种关系转化为出现过的其他插头
既:
上面的数据中:
laptop B而B->X->(A,D)
虽然X未出现在数据中所给的插头,不过却可以把A,D转化为B,那么也就是说
laptop ->(A,B,D)
为什么没有X?因为X不在所给的插头中,既根本就没这个插头,如何匹配?
如何获得这些等价关系?对插头全集做一次floyd既可
#include<iostream>
#include<map>
#include<string>
using namespace std;
#define N 401
bool mat[N][N],mark[N],omat[N][N],mat2[N][N];
int n,m,mch[N];
bool dfs(int pre)
{
int i;
for(i=0;i<m;++i)
if(mat[pre][i]&&!mark[i])
{
mark[i]=true;
int t=mch[i];
mch[i]=pre;
if(t==-1||dfs(t))return true;
mch[i]=t;
}
return false;
}
int mfit()
{
memset(mch,-1,sizeof(mch));
int i,sum=0;
for(i=0;i<n;++i){memset(mark,false,sizeof(mark));if(dfs(i))sum++;}
return sum;
}
map<string,int> M,K;
map<string,int>::iterator p;
string a,b;
int P[N];
int main()
{
int i,j,k;
int nn,t;
//OPEN
char buf[101],to[101];
while(scanf("%d",&m)!=EOF){
M.clear();
K.clear();
memset(mat,false,sizeof(mat));
memset(omat,false,sizeof(omat));
while(getchar()!='\n');
for(i=0;i<m;++i)
{
gets(buf);
a=buf;
M[a]=i;
}
nn=m;
scanf("%d",&n);
while(getchar()!='\n');
for(i=0;i<n;++i)
{
scanf("%s%s",buf,to);
b=to;
p=M.find(b);
if(p==M.end())M[b]=m,m++;
P[i]=M[b];
}
scanf("%d",&t);
while(getchar()!='\n');
while(t--)
{
scanf("%s%s",buf,to);
a=buf;
b=to;
if((p=M.find(a))==M.end())M[a]=m,m++;
if((p=M.find(b))==M.end())M[b]=m,m++;
int x=M[a],y=M[b];
omat[x][y]=true;
}
for(i=0;i<m;++i)
omat[i][i]=true;
for(k=0;k<m;++k)
for(i=0;i<m;++i)
for(j=0;j<m;++j)
omat[i][j]=omat[i][j]||(omat[i][k]&&omat[k][j]);
for(i=0;i<n;++i)
{
for(j=0;j<nn;++j)
if(omat[P[i]][j])
mat2[i][j]=true;
}
for(i=0;i<n;++i)
for(j=0;j<nn;++j)
mat[i][j]=mat2[i][j];
m=nn;
printf("%d\n",n-mfit());
}
return 0;
}

转载于:https://www.cnblogs.com/myth-peng/p/3228126.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值