这个题是说在一个会议室里有n种插座,每种插座一个,每个插座只能插一种以及一个电器或者购买适配器使得其他接口的设备可以用。有m个设备,每个设备需要接到指定的插座上,并非所有的设备都可以插到插座上。有k中适配器可以选择(数量无限),eg适配器(a,b) 表示可以把b类插座变为a类插座,让你求出至少有多少个设备无法使用。
思路:
1、不难想到这个题应该用最大流做,最后总的设备数减最大流即为所求答案。
2、建图的时候将源点与对应插座编号(自己编号)相连,权值为当前插座个数。
3、将对应插座与汇点相连,权值为对应的设备数量。
4、将适配器对应相连,权值为无穷大。
5、跑最大流即可,我用的Dinic
注意:
1、设备所需的插座可能存在前面没有提供的情况,需考虑加边。
2、适配器可能2边转换都在设备需要插座与插座都没出现过,但它可以起到中转的作用,所以适配器的时候每个都要考虑加新边的情况
3、题目中点说是100,但实际好像是500+,边数要计算好
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=600;
const int maxm=30000;
const int inf=1<<29;
int n,m,k,e,st,des,num,head[maxn],pnt[maxm],nxt[maxm],flow[maxm],level[maxn],q[maxn],cnta[maxn],cntb[maxn];
char str[maxn][30];
void AddEdge(int u,int v,int c)
{
pnt[e]=v;nxt[e]=head[u];flow[e]=c;head[u]=e++;
pnt[e]=u;nxt[e]=head[v];flow[e]=0;head[v]=e++;
}
bool BFS()
{
memset(level,0,sizeof(level));
level[st]=1;
int pre=0,last=0;
q[last++]=st;
while(pre<last)
{
if(q[pre]==des)
return true;
for(int i=head[q[pre]];i!=-1;i=nxt[i])
if(flow[i]&&!level[pnt[i]])
{
level[pnt[i]]=level[q[pre]]+1;
q[last++]=pnt[i];
}
pre++;
}
return false;
}
int DFS(int u,int sum)
{
if(u==des)
return sum;
for(int i=head[u],t;i!=-1;i=nxt[i])
if(flow[i]&&level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(sum,flow[i]))))
{
flow[i]-=t;
flow[i^1]+=t;
return t;
}
return level[u]=0;
}
int maxflow()
{
int ans=0;
while(BFS())
while(1)
{
int val=DFS(st,inf);
if(!val)
break;
ans+=val;
}
return ans;
}
int GetNum(char *name)
{
for(int i=1;i<num;i++)
if(!strcmp(str[i],name))
return i;
return -1;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
e=0,num=1;
memset(head,-1,sizeof(head));
memset(cnta,0,sizeof(cnta));
memset(cntb,0,sizeof(cntb));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",str[num]);
int index=GetNum(str[num]);
if(index==-1)
cnta[num++]++;
else
cnta[index]++;
}
scanf("%d",&m);
char a[101],b[30];
for(int i=0;i<m;i++)
{
scanf("%s%s",a,b);
int index=GetNum(b);
if(index==-1)
{
strcpy(str[num],b);
cntb[num++]++;
}
else
cntb[index]++;
}
st=0,des=num++;
for(int i=1;i<num;i++)
{
if(cnta[i])
AddEdge(i,des,cnta[i]);
if(cntb[i])
AddEdge(st,i,cntb[i]);
}
scanf("%d",&k);
for(int i=0;i<k;i++)
{
scanf("%s%s",a,b);
int numa=GetNum(a);
int numb=GetNum(b);
if(numa==-1)
{
strcpy(str[num],a);
numa=num++;
}
if(numb==-1)
{
strcpy(str[num],b);
numb=num++;
}
AddEdge(numa,numb,inf);
}
printf("%d\n",m-maxflow());
}
return 0;
}