二分匹配(dfs实现)+floyd

来源:互联网 发布:115会员淘宝购买 编辑:程序博客网 时间:2024/05/16 05:14

本题题意:一个房间里有n个插座,插座的名称为一个字符串,有m台机器,机器有他对应的插座,有k个转换器,转化器可以将:如 A B 将插座A转化为插座B。求最少有几台机器没有插到插座(其实就是求二分匹配)。

分析:本题目可以将装唤器下边的数据floyd,建立联通关系。然后就构建从机器到插座的邻接矩阵,然后使用匈牙利算法。

#include<iostream>  
#include<memory.h>  
#include<string>  
#include<cstdio>  
#include<algorithm>  
#include<math.h>  
#include<stack>  
#include<queue>  
#include<vector>  
#include<map>  
using namespace std;
char cn[409],jjn[409],cnn[409],st[409],en[409];
int ha[409][409],f[409][409],save[409],match[409],visited[409];
int n,m;
bool DFS(  int k)
{
      for(int i = 1; i <=n; i++)
           if( ha[k][i] && !visited[i]    )
          {
               visited[i] = true;
             if( match[i] == -1 || DFS(match[i]) )   //寻找是否为增广路径
         {
           match[i] = k;            //路径取反操作。
           return true;
              }
          }
       return false;
}
 
int main()
{
map<string,int>mpc;
map<string,int>mpj;
int i,j,k,cnt;

scanf("%d",&n);//有n个插座,插座名为
for(i=1;i<=n;i++)
{
  scanf("%s",cn);
       mpc[cn]=i;
}
cnt=n;
scanf("%d",&m);//机器
for(i=1;i<=m;i++)
{
  scanf("%s%s",jjn,cnn);
  mpj[jjn]=i;
  if(mpc[cnn]==0)
  {
  mpc[cnn]=(++cnt);
  }
  ha[mpj[jjn]][mpc[cnn]]=1;
  save[mpj[jjn]]=mpc[cnn];
}
scanf("%d",&k);
for(i=1;i<=k;i++)
{
scanf("%s%s",st,en);
if(mpc[st]==0)
{
mpc[st]=(++cnt);
}
if(mpc[en]==0)
{
mpc[en]=(++cnt);
}
f[mpc[st]][mpc[en]]=1;
}
//printf("haha\n");
for(k=1;k<=cnt;k++)
for(i=1;i<=cnt;i++)
for(j=1;j<=cnt;j++)
{
if(f[i][k]==1&&f[k][j]==1)
f[i][j]=1;
}
for(i=1;i<=m;i++)
{
for(j=1;j<=cnt;j++)
if(f[save[i]][j]==1)
ha[i][j]=1;
}

int     count = 0;
       memset(match, -1, sizeof(match));
      
       for(i = 1; i<=m; i++)
      {    //以二分集中的较小集为n进行匹配较优
            memset(visited, 0,sizeof(visited));
            if( DFS(i) )     ++count;    //count为匹配数
       }
       cout<<m-count<<endl;
return 0;
}
   

原创粉丝点击