hdu 2389 比匈牙利算法更快的Hopcroft-Karp算法模板题

题意:从具体情境中抽象出m个点匹配n个点。m,n<=3000。

题解:Hopcroft-Karp算法

1.匈牙利算法O(V * E)有详细图解,但是Hopcroft-Karp算法O(V^0.5 * E)死活没有搜索到图解博客。看代码大概知道是批量找增广路,但具体怎么找没有很清晰的印象,但是掌握了模板还是好了一些。

2.模板:https://blog.csdn.net/becky_w/article/details/78230102

#include<stdio.h>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#define MAXN 3005
#define inf 0x3f3f3f3f
using namespace std ;
int m , n ;
int dx[MAXN] , dy[MAXN] ;
bool edge[MAXN][MAXN] ;
bool used[MAXN] ;
int mx[MAXN] , my[MAXN] ;
bool search_path()
{
   queue <int> q ;
   memset(dx , -1 , sizeof(dx)) ;
   memset(dy , -1 , sizeof(dy)) ;
   int i , j , k ;
   int a , b ;
   int dis = inf ;
   for(i = 1 ; i <= m ; i ++)
       if(mx[i] == -1)
       {
       	 dx[i] = 0 ;
       	 q.push(i) ;
	   }
   while(!q.empty())
   {
   	 a = q.front() ;
   	 q.pop() ;
   	 if(dx[i] >= dis)
   	    break ;
   	 for(i = 1 ; i <= n ; i ++)
   	 {
   	    if(edge[a][i] && dy[i] == -1)
		{
		  dy[i] = dx[i] + 1 ;
		  if(my[i] == -1) 
		     dis = dy[i] ;
		  else
		  {
		  	 dx[my[i]] = dy[i] + 1 ;
		     q.push(my[i]) ;	
		  }	
		}	
	 }
   }
   return dis != inf ;
}
bool dfs(int u)
{
   int i , j ;
   for(i = 1 ; i <= n ; i ++)
   {
      if(edge[u][i] && !used[i])
	  {
	    used[i] = 1 ;
		if(my[i] == -1 || dfs(i))
		{
		  mx[u] = i ;
		  my[i] = u ;
		  return 1 ;	
		}	
	  }	
   }
   return 0 ;	
}
int Match()
{
	int i , j ;
	int ans = 0 ;
	memset(mx , -1 , sizeof(mx)) ;
	memset(my , -1 , sizeof(my)) ;
	while(search_path())
	{
		memset(used , 0 , sizeof(used)) ;
		for(i = 1 ; i <= m ; i ++)
		{
			if(mx[i] == -1 && dfs(i))
			   ans ++ ;
		}
	}
	return ans ;
}
int main()
{
	int t ;
	int i , j , k ;
	int cnt ;
	int px[MAXN] , py[MAXN] , s[MAXN] ;
	int ux[MAXN] , uy[MAXN] ;
	int ans ;
	scanf("%d" , &k) ;
	cnt = 0 ;
	while(k --)
	{
		scanf("%d" , &t) ;
		scanf("%d" , &m) ;
		for(i = 1 ; i <= m ; i ++)
		    scanf("%d%d%d" , &px[i] , &py[i] , &s[i]) ;
		scanf("%d" , &n) ;
		for(i = 1 ; i <= n ; i ++)
		    scanf("%d%d" , &ux[i] , &uy[i]) ;
		memset(edge , 0 , sizeof(edge)) ;
		for(i = 1 ; i <= m ; i ++)
		    for(j = 1 ; j <= n ; j ++)
		        if((px[i] - ux[j]) * (px[i] - ux[j]) + (py[i] - uy[j]) * (py[i] - uy[j]) <= s[i] * s[i] * t * t) 
	               edge[i][j] = 1 ;
	    ans = Match() ;
		printf("Scenario #%d:\n%d\n\n" , ++cnt , ans) ;
	}
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值