题解:
乍一看,很难把这题与二分图最大匹配联系起来。但我们来仔细分析下,对于样例数据,我们的方案是第1行与第二列,可以想象,对于任何数据,我们的方案描述是,一些行数与一些列数,那么抽象一下,就是两个点集,比如样例,就是(1),(2)两个点集,发现了没?这是不是像二分图的最小点覆盖模型?但边是啥?既然我们要覆盖的是所有的敌人,且每个敌人都有对应的横纵坐标,那么对应点的构造,那么边就是敌人横纵坐标构成的,即如果敌人位于(i,j),那么i和j之间有一条边。至此,这题转化为求二分图的最小顶点覆盖,又由Konig定理可知,二分图最小顶点覆盖数=最大匹配数,所以这题解决了。鉴于这题的数据量,采用匈牙利算法求二分图最大匹配即可。
#include<stdio.h>
#include<string.h>
intnum,visit[501],match[1001],key[10010],next[10010],head[510];
int find(int x)
{
intk,i;
for(i=head[x];i!=-1;i=next[i])
{
k=key[i];
if(!visit[k])
{
visit[k]=1;
if (!match[k]||find(match[k]))
{
match[k]=x;
return1;
}
}
}
return0;
}
int main()
{
intn,t,k,i,ans,vi,vj;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
memset(head,-1,sizeof(head));
memset(match,0,sizeof(match));
num=0;
for(i=1;i<=k;i++)
{
scanf("%d%d",&vi,&vj);
key[num]=vj;
next[num]=head[vi];
head[vi]=num++;
}
for (i=1,ans=0;i<=n;i++)
{
memset(visit,0,sizeof(visit));
if(find(i)) ans++;
}
printf("%d\n",ans);
}
return0;
}
这题难点在于如何建图,这也再次说明了图论中建图是多么困难的,只有不断积累经验,还有总结,才能把那些形形色色看似毫无头绪的问题与图关联起来。