房间里有n个插头m个插座与k个转换器,转换器能将特定的插头接到特定的插座上,求最少剩几个插头无法匹配。
建图
连接超级源与所有插头且容量为1
连接所有插座与超级汇且容量为1
连接所有配对的插头与转换器且容量为1
连接所有能配对的转换器与插头或插座且容量为INF
/**********
Dinic
**********/
#include <queue>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 500
#define INF 0x3f3f3f3f
struct ed
{
int to,cap,next;
}e[maxn*4];
int F,N,D,Start=1,End,cnt=0; //Start为超级源End为超级汇
int level[maxn*2],head[maxn];
char receptacles[maxn][30],plug[maxn][30],pin[maxn][30],pout[maxn][30];
void add(int from,int to,int cap)
{
e[cnt].to=to;
e[cnt].cap=cap;
e[cnt].next=head[from];
head[from]=cnt++;
swap(from,to);
e[cnt].to=to;
e[cnt].cap=0;
e[cnt].next=head[from];
head[from]=cnt++;
}
bool bfs()
{
memset(level,-1,sizeof(level));
level[Start]=0;
queue<int>q;
q.push(Start);
while(!q.empty())
{
int i,u=q.front();
q.pop();
for(i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(e[i].cap>0&&level[v]==-1)
{
level[v]=level[u]+1;
q.push(v);
}
}
}
return level[End]!=-1;
}
int dfs(int u,int f)
{
if(u==End||!f) return f;
int k,i;
for(i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(e[i].cap>0&&level[u]+1==level[v])
{
k=dfs(v,min(f,e[i].cap));
if(k>0)
{
e[i].cap-=k;
e[i^1].cap+=k;
return k;
}
}
}
level[u]=-1;
return 0;
}
int dinic()
{
int s=0,f;
while(bfs())
{
while((f=dfs(Start,INF))>0) s+=f;
}
return s;
}
int main()
{
int i,n,m,p,j;
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(i=1;i<=n;i++)
{
scanf("%s",receptacles[i]);
add(Start,i+Start,1);
}
scanf("%d",&m);
for(i=1;i<=m;i++) scanf("%*s %s",plug[i]);
scanf("%d",&p);
End=Start+n+p+m+1; //计算超级汇
for(i=1;i<=m;i++)
{
add(Start+n+p+i,End,1);
for(j=1;j<=n;j++)
if(strcmp(receptacles[j],plug[i])==0) add(Start+j,Start+n+p+i,1);
}
for(i=1;i<=p;i++) scanf("%s %s",pin[i],pout[i]);
for(i=1;i<=p;i++)
{
for(j=1;j<=n;j++)
if(strcmp(receptacles[j],pin[i])==0 || strcmp(receptacles[j],pout[i])==0)
add(Start+j,Start+n+i,1);
for(j=1;j<=m;j++)
if(strcmp(plug[j],pout[i])==0 || strcmp(plug[j],pin[i])==0)
add(Start+n+i,Start+n+p+j,1);
}
for(i=1;i<=p;i++)
{
for(j=1;j<=p;j++)
{
if(i!=j&&strcmp(pin[i],pout[j])==0) add(Start+n+i,Start+n+j,INF);
if(i!=j&&strcmp(pout[i],pin[j])==0) add(Start+n+i,Start+n+j,INF);
}
}
printf("%d\n",m-dinic());
return 0;
}