poj 3041 匈牙利算法 最小点覆盖

题意:

一个N * N的矩阵,每个格子有些行星,有种特殊武器,一次能消灭一行,或一列,问最少使用多少次这样得武器,可以消灭所有行星。

构图:

刚开始的思路是最少的边覆盖所有点,这个边是要么平行X轴,要么平行Y轴。

显然这样,这个边无法构图,起点终点都不知。

转换思路, 既然平行X轴,Y轴的边无法构造,是否可以平行X轴或Y轴的边把它看作一个点呢?

同时分成两个集合,一个集合X(1-N),一个集合Y(1-N),一个点(a,b)就从X集合中的点A

连一条边指向集合Y中的B。这样的定义构图就完全符合二分图的定义。

二分图的定义:

1.可以分成两个集合,一个X,一个Y

2.任何一条边的两个端点都分属于不同集合

3.任何一个集合内部不存在边

构图完毕,现在要解决得问题是如何用最少得点覆盖所有的边。

由匈牙利算法求这个二分图最大匹配就是答案,

也就是 最少覆盖点 = 最大匹配。证明 http://www.matrix67.com/blog/archives/116

View Code
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int N, M;
int mp[510][510];
int match[510];
bool color[510];

int find( int x )
{
  for( int i = 1; i <= N; i++)
  {
     if( !color[i] && mp[x][i] )
     {
         color[i] = true;
         if( match[i] == -1 || find( match[i] ))
         {
            match[i] = x;
            return 1;
         }
   
     }

  }
  return 0;
}

void solve( )
{
   int ans = 0;
   memset(match,-1,sizeof(match));
   for( int i = 1; i <= N; i++)
   {
      memset(color, 0, sizeof(color));
      if( find(i) )
    ans++;
   }
   printf("%d\n",ans);
}

int main( )
{
   int a, b;
   while( scanf("%d%d", &N, &M) != EOF)
   {
     for( int i = 1; i <= N; i++)
    for( int j = 1; j <= N; j++)
      mp[i][j] = 0;
     for( int i = 1; i <= M; i++)
     {
         scanf("%d%d",&a,&b);
         mp[a][b] = 1;
     }
     solve( );
   }
   return 0;
}

转载于:https://www.cnblogs.com/tangcong/archive/2012/07/14/2591091.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值