Windows-Server-2003/ds/lhmatch/lhonline.c

172 lines
4.7 KiB
C
Raw Permalink Normal View History

2024-08-04 01:28:15 +02:00
/******************************************************************************
*
* LHMatch Online
*
* Authors: Nicholas Harvey and Laszlo Lovasz
*
* Developed: April 2001
*
* Algorithm Description:
*
* Let S be {}
* Let M be {}
* While S != U Do
* Assert( S is a subset of U )
* Assert( M is an optimal LH matching of G restricted to S \union V )
* Let x \member U \ S
* For each edge (u,v) in E
* If (u,v) \member M, orient this edge from v to u
* Else, orient this edge from u to v
* Build a directed breadth-first search tree rooted at x
* Let y be a vertex in the BFS tree \intersection V with minimum M-degree
* Alternate along the unique x->y dipath, increasing the size of M by one
* Add x to S
* Repeat
*
* This algorithm is called online because the optimality of the matching is
* maintained as the size increases.
*
* Runtime:
*
* The worst-case runtime is O(|U| * |E|), but in practice it is quite slow.
*
******************************************************************************/
/***** Header Files *****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "LHMatchInt.h"
/***** EnqueueNbr *****/
/* Enqueue all neigbours of this vertex which have not yet been visited.
* If 'matchedOnly' is true, enqueue only the matched-neigbours. */
static void EnqueueNbr(Graph *g, Vertex *v, char matchedOnly) {
Vertex *n;
int i;
for(i=0;i<v->degree;i++) {
n=v->adjList[i];
if( !matchedOnly || n->matchedWith==v ) {
if( n->parent==NULL ) {
DPRINT( printf("Adding %d to queue with parent %d\n",n->id,v->id); )
g->Queue[g->Qsize++]=n;
n->parent=v;
} else {
DPRINT( printf("Not adding %d to queue -- already there\n",n->id); )
}
}
}
}
/***** UpdateMinRHSLoad *****/
static void UpdateMinRHSLoad(Graph *g) {
int i;
g->minRHSLoad = g->numLHSVtx;
for(i=0;i<g->numRHSVtx;i++) {
g->minRHSLoad = INTMIN(g->minRHSLoad,g->rVtx[i].numMatched);
}
}
/***** AugmentPath *****/
/* Found an augmenting path. Switch the matching edges along it. */
static void AugmentPath(Graph *g, Vertex *u, Vertex *v) {
Vertex *w,*p;
DPRINT( printf("V: %d. Increase load to %d\n", v->id, v->numMatched+1 ); )
/* Switch along the path */
w=v;
w->numMatched++;
do {
p=w->parent;
p->matchedWith=w;
w=p->parent;
} while(p!=u);
assert(w==p);
/* Update minRHSLoad */
if( v->numMatched==g->minRHSLoad+1 ) {
UpdateMinRHSLoad(g);
}
}
/***** BFS *****/
/* Perform a breadth-first search rooted at node i. */
static Vertex* BFS(Graph *g,Vertex *u) {
Vertex *bestV,*v;
int q;
/* Start a BFS from u */
DPRINT( printf("Using %d as root\n",u->id); )
u->parent=u;
g->Queue[0]=u; g->Qsize=1;
bestV=NULL;
/* Process the vertices in the queue */
for(q=0;q<g->Qsize;q++) {
v = g->Queue[q];
DPRINT( printf("Dequeued %d: ",v->id); )
if(IS_LHS_VTX(v)) {
/* Its a LHS-vertex; enqueue all neigbours */
DPRINT( printf("LHS -> Enqueuing all nbrs\n"); )
EnqueueNbr(g, v, FALSE);
} else {
/* Its a RHS-vertex; enqueue all matched-neighbours */
DPRINT( printf("RHS -> Enqueuing all %d matched-nbrs\n",
v->numMatched); )
EnqueueNbr(g, v, TRUE);
if( NULL==bestV || v->numMatched<bestV->numMatched ) {
bestV=v;
if( v->numMatched==g->minRHSLoad ) {
/* v has the minimum M-degree out of all RHS vertices.
* We can stop the BFS prematurely. */
break;
}
}
}
}
return bestV;
}
/***** LHAlgOnline *****/
int LHAlgOnline(Graph *g) {
Vertex *bestV;
int i,j,err;
DPRINT( printf("--- LHMatch Online Started ---\n"); )
g->minRHSLoad=0;
err = InitializeQueue(g);
if( LH_SUCCESS!=err ) {
return err;
}
UpdateMinRHSLoad(g);
/* Examine every vtx on LHS */
for(i=0;i<g->numLHSVtx;i++) {
/* Build a BFS tree and find the best augmenting path */
bestV = BFS(g,&(g->lVtx[i]));
/* If bestV is null, lVtx[i] must have degree 0 */
if( NULL!=bestV ) {
DPRINT( printf("Best aug. path is from %d to %d\n",g->lVtx[i].id,bestV->id); )
AugmentPath(g,&(g->lVtx[i]),bestV);
}
/* Clear the marks on all nodes in the BFS tree */
for(j=0;j<g->Qsize;j++) {
g->Queue[j]->parent=NULL;
}
}
DestroyQueue(g);
DPRINT( printf("--- LHMatch Online Finished ---\n"); )
return LH_SUCCESS;
}