POJ 1087 A Plug for UNIX

23 篇文章 0 订阅

二分图匹配,主要在于建图,貌似建得有点丑。。把能插座X上能插入的插头(包括通过转化器的)通过dfs全找出来,图就建好了,我是用map将字符串映射成数组下标的。

二分图一边是插座,一边是插头。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>

using namespace std;

const int maxN=110;
map<string,int> ind;
int n,m,k,cnt,link[maxN];
string plug[maxN],rec[maxN],name,s1,s2;
bool G[maxN*10][maxN*10],g[maxN*10][maxN*10],used[maxN],vis[maxN*10];

void build(int i,int u){
    for(int v=0;v<cnt;v++)
        if(G[u][v]&&!vis[v]){
            g[i][v]=true;
            vis[v]=true;
            build(i,v);
        }
}

bool dfs(int u){
    for(int v=0;v<n;v++){
        int uu=ind[plug[u]],vv=ind[rec[v]];
        if(g[vv][uu]&&!used[v]){
            used[v]=true;
            if(link[v]==-1||dfs(link[v])){
                link[v]=u;
                return true;
            }
        }
    }
    return false;
}

int main(){
#ifndef ONLINE_JUDGE	          
	freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    while(cin>>n){
        cnt=0;
        memset(G,false,sizeof(G));
        memset(g,false,sizeof(g));
        for(int i=0;i<maxN*10;i++) G[i][i]=true;
        for(int i=0;i<n;i++){
            cin>>rec[i];
            if(!ind.count(rec[i])) ind[rec[i]]=cnt++;
        }
        cin>>m;
        for(int i=0;i<m;i++){
            cin>>name>>plug[i];
            if(!ind.count(plug[i])) ind[plug[i]]=cnt++;
        }
        cin>>k;
        for(int i=0;i<k;i++){
            cin>>s1>>s2;
            if(!ind.count(s1)) ind[s1]=cnt++;
            if(!ind.count(s2)) ind[s2]=cnt++;
            G[ind[s2]][ind[s1]]=true;
        }
        for(int i=0;i<cnt;i++){
            memset(vis,false,sizeof(vis));
            build(i,i);
        }
        //for(int i=0;i<cnt;i++){
          //  for(int j=0;j<cnt;j++)
            //    cout<<g[i][j]<<' ';
            //cout<<endl;
        //}
        memset(link,-1,sizeof(link));
        int res=0;
        for(int i=0;i<m;i++){
            memset(used,false,sizeof(used));
            if(dfs(i)) res++;
        }
        cout<<m-res<<endl;
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值