Hopcroft_Karp算法

匈牙利算法中,我们每次寻找一条增广路来增加匹配集合M.可以证明,每次找增广路的复杂度是O(E),一共需要增广O(V)次,因此总时间复杂度为O(VE).为了降低时间复杂度,在Hopcroft Karp算法中,我们在增加匹配集合M时,每次寻找多条增广路.可以证明,这样迭代次数最多为2*V^0.5,所以,时间复杂度就降到了O(V^0.5*E).

hdoj 2389  Rain on your Parade

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <iterator>
using namespace std;

struct NodeGuest
{
    double x, y, speed;
}ng[3010];

struct NodeNmbre
{
    double x, y;
}nn[3010];


int T, cntGuest, cntUmbre, match;
int disx[3010], disy[3010], matx[3010], maty[3010], que[3010];
double t;
vector<int> mp[3010];



double getTime(int a, int b)
{
    double dis = sqrt( (ng[a].x - nn[b].x) * (ng[a].x - nn[b].x) + (ng[a].y - nn[b].y) * (ng[a].y - nn[b].y));
    return dis/ng[a].speed;
}


bool bfs()
{
	int i, j, fore = 0, rear = 0;
	bool flag = false;
	vector<int>::iterator ite;
	for(i=0; i<cntGuest; ++i){  //找出中还没有匹配的点
		if(matx[i] == -1) que[rear++] = i;
		disx[i] = 0;
	}
	for(i=0; i<cntUmbre; ++i) disy[i] = 0;
	while(fore<rear){//从这些没有匹配的点里,找路径
		int x = que[fore++];
		for(ite=mp[x].begin(); ite!=mp[x].end(); ++ite){
			if(disy[*ite] == 0){
				disy[*ite] = disx[x] + 1;
				if(maty[*ite] == -1) flag = true; //找到一条路径,则返回值是正的
				else {         //找不到路径,则把前向点如队列
					disx[maty[*ite]] = disy[*ite] + 1;
					que[rear++] = maty[*ite];
				}
			}
		}
	}
    return flag;
}



bool dfs(int x)
{
	vector<int>::iterator ite;
	for(ite=mp[x].begin(); ite!=mp[x].end(); ++ite){
		if(disy[*ite] == disx[x] + 1){
			disy[*ite] = 0;
			if(maty[*ite] == -1 || dfs(maty[*ite])){
				matx[x] = *ite;
				maty[*ite] = x;
				return 1;
			}
		}
	}
	return false;
}



int Hopcroft_Karp()
{
	int i;
	match = 0;
	memset(matx, -1, sizeof(matx));
	memset(maty, -1, sizeof(maty));
	while(bfs()){
		for(i=0; i<cntGuest; ++i){
			if(matx[i] == -1 && dfs(i)) ++match;
		}
	}
	return match;
}


int main()
{
//    freopen("c:/aaa.txt", "r", stdin);
    int ca = 1;
    scanf("%d", &T);
    while(T--){
        scanf("%lf %d", &t, &cntGuest);
        int i, j;
        for(i=0; i<cntGuest; ++i) scanf("%lf %lf %lf", &ng[i].x, &ng[i].y, &ng[i].speed);
        scanf("%d", &cntUmbre);
        for(i=0; i<cntUmbre; ++i) scanf("%lf %lf", &nn[i].x, &nn[i].y);
        for(i=0; i<cntGuest; ++i) mp[i].clear();
        for(i=0; i<cntGuest; ++i){
            for(j=0; j<cntUmbre; ++j){
                double tt = getTime(i, j);
                if(tt <= t) mp[i].push_back(j);
            }
        }

        printf("Scenario #%d:\n%d\n\n", ca++, Hopcroft_Karp());
    }
    return 0;
}


posted on 2010-12-26 17:46  CrazyAC  阅读(3989)  评论(0编辑  收藏  举报