POJ 1087 A Plug for UNIX(二分图匹配)

来源:互联网 发布:rebecca minkoff知乎 编辑:程序博客网 时间:2024/05/23 01:54

用set做字符串到标号的映射。

用floyd做一下可转移关系的传递,确定每两种端口间是否能转移。

然后根据这个关系建图,如果第i个空余端口可以转移成第j个需求端口,就从i到j建一条边。之后跑一个匈牙利算法即可。


注意floyd前,要把每个点到自己的转移可能初始化为1


坑:空间要开到400,因为理论上最多有400个不一样的端口出现。


代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>using namespace std;#include <map>int N,M,K;map<string,int> Hs;int Num=0,tot=0;bool plug[405][405];int dev[405];int rec[405];int sM[405];int tM[405];bool m[405][405];bool vis[405];bool dfs(int u){for(int i=0;i<M;i++){if(m[u][i]&&!vis[i]){vis[i]=1;if(tM[i]==-1||dfs(tM[i])){tM[i]=u;sM[u]=i;return 1;}}}return 0;}int solve(){int res=0;for(int i=0;i<N;i++){if(sM[i]==-1){memset(vis,0,sizeof(vis));if(dfs(i)) res++;}}return res;}int main(){scanf("%d",&N);for(int i=0;i<N;i++){string t;cin>>t;if(!Hs.count(t)) Hs[t]=Num++;rec[i]=Hs[t];}scanf("%d",&M);for(int i=0;i<M;i++){string t,k;cin>>k>>t;if(!Hs.count(t)) Hs[t]=Num++;dev[i]=Hs[t];}scanf("%d",&K);for(int i=0;i<K;i++){string s,t;cin>>t>>s;if(!Hs.count(s)) Hs[s]=Num++;if(!Hs.count(t)) Hs[t]=Num++;plug[Hs[s]][Hs[t]]=1;}for(int i=0;i<Num;i++){plug[i][i]=1;}for(int k=0;k<Num;k++){for(int i=0;i<Num;i++){for(int j=0;j<Num;j++){if(plug[i][k]&&plug[k][j]) plug[i][j]=1;}}}for(int i=0;i<N;i++){for(int j=0;j<M;j++){if(plug[rec[i]][dev[j]]){m[i][j]=1;}}}memset(sM,-1,sizeof(sM));memset(tM,-1,sizeof(tM));int res=M-solve();printf("%d",res);return 0;}

0 0