POJ 1087&&HDU 1526 A Plug for UNIX (二分图+Floyd传递闭包 )

   题目大意: 有n个插座,下边n行分为为插座的类型,m个电器,m行分别代表电器的名称和插头的类型.

最后,有k行数据每组,对应适配器的插座和插头的类型.


   思路:将所有的插座,插头编上序号,同时给自己也要标记上插座和插头(均是自身和自身间的关系),然

后给,适配器的插座和插头建立联系.之后进行Floyd的传递闭包链接有间接性关系图.最后匹配,但注意

要进行"编号"与"编号"之间的匹配.

4 
A 
B 
C 
D 
5 
laptop B 
phone C 
pager B 
clock B 
comb X 
3 
B X 
X A 
X D


#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
int n,m,cro[1000],s,re[1000],gs[1000];
bool Map[1000][1000],use[1000];
char a[1000],b[1000];
void Floyd()
{int i,j,k;
    for(k=1;k<s;k++)
        for(i=1;i<s;i++)
            for(j=1;j<s;j++)
                if(Map[i][k]&&Map[k][j])
                    Map[i][j]=true;
}
int DFS(int v)
{int i,j,k;
    for(i=1;i<=n;i++)
        if(!use[re[i] ]&&Map[gs[v]][re[i] ])
        {
            use[re[i] ]=true;
            if(cro[re[i] ]==-1||DFS(cro[ re[i] ] ))
            {
                cro[re[i] ]=v;
                return 1;
            }
        }
    return 0;
}
int main()
{int i,j,k;
    map<string,int>K;
    while(~scanf("%d",&n))
    {
        getchar();
        K.clear();s=1;memset(cro,-1,sizeof(cro));memset(Map,false,sizeof(Map));
        for(i=1;i<=n;i++)
        {
            scanf("%s",a);
            if(!K[a]) K[a]=s++;
            re[i]=K[a];
            Map[re[i]][re[i]]=true;
        }
        scanf("%d",&m);
        for(i=1;i<=m;i++)
        {
            scanf("%s %s",a,b);
            if(!K[b]) K[b]=s++;
            gs[i]=K[b];
            Map[K[b] ][K[b] ]=true;
        }
        scanf("%d",&k);getchar();
        for(i=1;i<=k;i++)
        {
            scanf("%s %s",a,b);
            if(!K[a]) K[a]=s++;
            if(!K[b]) K[b]=s++;
            Map[K[a]][K[b]]=true;
        }
        Floyd();
        int ans=0;
        for(i=1;i<=m;i++)
        {memset(use,false,sizeof(use));
            ans+=DFS(i);
        }
        cout<<m-ans<<endl;
    }
    return 0;
}


你可能感兴趣的:(二分图)