题解: nyoj237 游戏高手的烦恼

题解:

乍一看,很难把这题与二分图最大匹配联系起来。但我们来仔细分析下,对于样例数据,我们的方案是第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;
}       

 这题难点在于如何建图,这也再次说明了图论中建图是多么困难的,只有不断积累经验,还有总结,才能把那些形形色色看似毫无头绪的问题与图关联起来。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值