匈牙利算法之POJ1087

17 篇文章 0 订阅
//题目的大意:有m个插头和n个插座..插头和插座匹配..中间可以通过调制器转换成其它匹配..
//最后问最多可以匹配多少对的问题.
//首先预处理把每个插头可以与哪个可以匹配的插头标记为1..不能匹配标记为0
//使用匈牙利算法一带就OK了..
//题目连接http://poj.org/problem?id=1087
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
const int inf = 0x3f3f3f;
const int MN = 200;
using namespace std;
char ct[MN][MN];
char cz[MN][MN],pzx[MN][MN],pzy[MN][MN];
int map[MN][MN],n,m,k;
int ppx[MN],ppy[MN];
bool mk[MN];
void find(int x ,char s[])
{
    for(int i = 1 ; i <= m ; i++)
    {
        if(!strcmp(s,ct[i]))
        {
            map[x][i] = 1;
        }
    }
}
void pipe(int x , char s[])
{
    for(int i = 1 ; i <= k ; i++)
    {
        if(!strcmp(s,pzy[i]))
        {
            find(x,pzx[i]);
            pipe(x,pzx[i]);
        }
    }
}
bool path(int x)
{
    for(int i = 1 ; i <= m ; i++)
    {
        if(map[x][i] && !mk[i])
        {
            mk[i] = 1;
            if(ppy[i] == -1 || path(ppy[i]))
            {
                ppy[i] = x;
                ppx[x] = i;
                return 1;
            }
        }
    }
    return 0;
}
int Maxmatch()
{
    int ans = 0;
    memset(ppx,0xff,sizeof(ppx));
    memset(ppy,0xff,sizeof(ppy));
    for(int i = 1 ; i <= n ; i++)
    {
       memset(mk,0,sizeof(mk));
       if(ppx[i] == -1)
       {
           ans += path(i);
       }
    }
    return ans;
}
int main()
{
    while(scanf("%d",&n) != EOF)
    {
        for(int i = 1 ; i <= n ; i++)
          scanf("%s",cz[i]);
        scanf("%d",&m);
        char h[111];
        for(int i = 1 ; i <= m ; i++)
        {
            scanf("%s",h);
            scanf("%s",ct[i]);
        }
        scanf("%d",&k);
        for(int i = 1 ; i <= k ; i++)
        {
            scanf("%s",pzx[i]);
            scanf("%s",pzy[i]);
        }
        for(int i = 1 ; i <= n ; i++)
          find(i,cz[i]);
        for(int i = 1 ; i <= n ; i++)
          pipe(i,cz[i]);
        int ans = m - Maxmatch();
        printf("%d\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值