#include
#include
#include
#define TRUE (1)
#define FALSE (0)
#define MAX_CITIES (10)
#define INFINITY (999)
#define I INFINITY
typedef int bool;
typedef struct _EDGE {
int head;
int tail;
} EDGE;
typedef struct _PATH {
EDGE edge[MAX_CITIES];
int edgesNumber;
} PATH;
typedef struct _MATRIX {
int distance[MAX_CITIES][MAX_CITIES];
int citiesNumber;
} MATRIX;
typedef struct _NODE {
int bound; MATRIX matrix; PATH path; struct _NODE* left; struct _NODE* right; } NODE;
int Simplify(MATRIX*);
EDGE SelectBestEdge(MATRIX);
MATRIX LeftNode(MATRIX, EDGE);
MATRIX RightNode(MATRIX, EDGE, PATH);
PATH AddEdge(EDGE, PATH);
PATH BABA(NODE);
PATH MendPath(PATH, MATRIX);
int MatrixSize(MATRIX, PATH);
void ShowMatrix(MATRIX);
void ShowPath(PATH, MATRIX);
main()
{
PATH path;
NODE root = {
0,
{{{I, 1, 2, 7, 5},
{1, I, 4, 4,
3},
{2, 4, I, 1,
2},
{7, 4, 1, I,
3},
{5, 3, 2, 3,
I}}, 5},
{{0}, 0},
NULL, NULL
};
root.bound += Simplify(&root.matrix);
path = BABA(root);
ShowPath(path, root.matrix);
return 0;
}
PATH BABA(NODE root)
{
int i;
static int minDist = INFINITY;
static PATH minPath;
EDGE selectedEdge;
NODE *left, *right;
puts("Current
Root:\n------------");
ShowMatrix(root.matrix);
printf("Root Bound:%d\n", root.bound);
if (MatrixSize(root.matrix, root.path) == 2)
{
if (root.bound <
minDist) {
minDist =
root.bound;
minPath =
MendPath(root.path, root.matrix);
getch();
return
(minPath);
}
}
selectedEdge = SelectBestEdge(root.matrix);
printf("Selected Edge:(%d, %d)\n",
selectedEdge.head + 1, selectedEdge.tail + 1);
left = (NODE *)malloc(sizeof(NODE));
right = (NODE *)malloc(sizeof(NODE));
if (left == NULL || right == NULL) {
fprintf(stderr,"Error
malloc.\n");
exit(-1);
}
left->bound = root.bound;
left->matrix =
LeftNode(root.matrix, selectedEdge);
left->path = root.path;
left->left = NULL;
left->right = NULL;
right->bound =
root.bound;
right->matrix =
RightNode(root.matrix, selectedEdge, root.path);
right->path =
AddEdge(selectedEdge, root.path);
right->left = NULL;
right->right = NULL;
left->bound +=
Simplify(&left->matrix);
right->bound +=
Simplify(&right->matrix);
root.left = left;
root.right = right;
puts("Right Branch:\n------------");
ShowMatrix(right->matrix);
puts("Left Branch:\n-----------");
ShowMatrix(left->matrix);
if (right->bound <
minDist) {
BABA(*right);
}
else {
printf("Current minDist is %d,
", minDist);
printf("Right Branch's Bound(=
%d).\n", right->bound);
printf("This branch is
dead.\n");
}
if (left->bound <
minDist) {
BABA(*left);
}
else {
printf("Current minDist is %d,
", minDist);
printf("Left Branch's Bound(=
%d).\n", left->bound);
printf("This branch is
dead.\n");
}
printf("The best answer now is %d\n",
minDist);
return (minPath);
}
PATH MendPath(PATH path, MATRIX c)
{
int row, col;
EDGE edge;
int n = c.citiesNumber;
for (row = 0; row < n;
row++) {
edge.head = row;
for (col = 0; col
< n; col++) {
edge.tail =
col;
if
(c.distance[row][col] == 0) {
path
= AddEdge(edge, path);
}
}
}
return path;
}
int Simplify(MATRIX* c)
{
int row, col, min_dist, h;
int n = c->citiesNumber;
h = 0;
for (row = 0; row < n; row++)
{
min_dist = INFINITY;
for (col = 0; col
< n; col++) {
if
(c->distance[row][col] < min_dist)
{
min_dist
= c->distance[row][col];
}
}
if (min_dist == INFINITY)
continue;
for (col = 0; col
< n; col++) {
if
(c->distance[row][col] != INFINITY) {
c->distance[row][col]
-= min_dist;
}
}
h += min_dist;
}
for (col = 0; col < n; col++)
{
min_dist = INFINITY;
for (row = 0; row
< n; row++) {
if
(c->distance[row][col] < min_dist)
{
min_dist
= c->distance[row][col];
}
}
if (min_dist == INFINITY)
continue;
for (row = 0; row
< n; row++) {
if
(c->distance[row][col] != INFINITY) {
c->distance[row][col]
-= min_dist;
}
}
h += min_dist;
}
return (h);
}
EDGE SelectBestEdge(MATRIX c)
{
int row, col;
int n = c.citiesNumber;
int maxD;
EDGE best, edge;
int D(MATRIX, EDGE);
maxD = 0;
for (row = 0; row < n; row++)
{
for (col = 0; col
< n; col++) {
edge.head =
row;
edge.tail =
col;
if
(!c.distance[row][col] && maxD < D(c, edge))
{
maxD
= D(c, edge);
best
= edge;
}
}
}
return (best);
}
int D(MATRIX c, EDGE edge)
{
int row, col, dRow, dCol;
int n = c.citiesNumber;
dRow = INFINITY;
for (col = 0; col < n; col++)
{
if (dRow <
c.distance[edge.head][col] && col != edge.tail) {
dRow =
c.distance[edge.head][col];
}
}
dCol = INFINITY;
for (row = 0; row < n; row++)
{
if (dCol <
c.distance[row][edge.tail] && row != edge.head) {
dCol =
c.distance[row][edge.tail];
}
}
return (dRow + dCol);
}
MATRIX LeftNode(MATRIX c, EDGE edge)
{
c.distance[edge.head][edge.tail] =
INFINITY;
return c;
}
MATRIX RightNode(MATRIX c, EDGE edge, PATH
path)
{
int row, col;
int n = c.citiesNumber;
EDGE loopEdge;
EDGE LoopEdge(PATH, EDGE);
for (col = 0; col < n;
col++)
c.distance[edge.head][col] =
INFINITY;
for (row = 0; row < n;
row++)
c.distance[row][edge.tail] =
INFINITY;
loopEdge = LoopEdge(path, edge);
c.distance[loopEdge.head][loopEdge.tail] =
INFINITY;
return (c);
}
EDGE LoopEdge(PATH path, EDGE edge)
{
int i, j;
EDGE loopEdge;
loopEdge.head = edge.tail;
loopEdge.tail = edge.head;
for (i = 0; i < path.edgesNumber;
i++) {
for (j = 0; j <
path.edgesNumber; j++) {
if
(loopEdge.head == path.edge[j].head) {
loopEdge.head
= path.edge[j].tail;
break;
}
}
}
for (i = 0; i < path.edgesNumber;
i++) {
for (j = 0; j <
path.edgesNumber; j++) {
if
(loopEdge.tail == path.edge[j].tail) {
loopEdge.tail
= path.edge[j].head;
break;
}
}
}
return (loopEdge);
}
PATH AddEdge(EDGE edge, PATH path)
{
path.edge[path.edgesNumber++] = edge;
return path;
}
int MatrixSize(MATRIX c, PATH path)
{
return (c.citiesNumber - path.edgesNumber);
}
void ShowPath(PATH path, MATRIX c)
{
int i, dist;
EDGE edge;
int n = path.edgesNumber;
dist = 0;
printf("\nThe path is: ");
for (i = 0; i < n; i++) {
edge = path.edge[i];
printf("(%d, %d) ", edge.head +
1, edge.tail + 1);
dist +=
c.distance[edge.head][edge.tail];
}
}
void ShowMatrix(MATRIX c)
{
int row, col;
int n = c.citiesNumber;
for (row = 0; row < n;
row++) {
for (col = 0; col
< n; col++) {
if
(c.distance[row][col] != INFINITY) {
printf("=",
c.distance[row][col]);
}
else {
printf(" -");
}
}
putchar('\n');
}
getch();
}