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