1.代码:

#include <stdio.h>
#include <malloc.h>

#define NoEdge           1000

struct MinHeapNode
{
	int lcost; //子树费用的下界
	int cc; //当前费用
	int rcost; //x[s:n-1]中顶点最小出边费用和
	int s; //根节点到当前节点的路径为x[0:s]
	int *x; //需要进一步搜索的顶点是//x[s+1:n-1]
	struct MinHeapNode *next;
};

int n; //图G的顶点数
int **a; //图G的邻接矩阵
//int   NoEdge;   //图G的无边标记
int cc; //当前费用
int bestc; //当前最小费用
MinHeapNode* head = 0; /*堆头*/
MinHeapNode* lq = 0; /*堆第一个元素*/
MinHeapNode* fq = 0; /*堆最后一个元素*/

int DeleteMin(MinHeapNode*&E)
{
	MinHeapNode* tmp = NULL;
	tmp = fq;
	// w = fq->weight ;
	E = fq;
	if(E == NULL)
		return 0;
	head->next = fq->next; /*一定不能丢了链表头*/
	fq = fq->next;
	// free(tmp) ;
	return 0;
}

int Insert(MinHeapNode* hn)
{
	if(head->next == NULL)
	{
		head->next = hn; //将元素放入链表中
		fq = lq = head->next; //一定要使元素放到链中
	}else
	{
		MinHeapNode *tmp = NULL;
		tmp = fq;
		if(tmp->cc > hn->cc)
		{
			hn->next = tmp;
			head->next = hn;
			fq = head->next; /*链表只有一个元素的情况*/
		}else
		{
			for(; tmp != NULL;)
			{
				if(tmp->next != NULL && tmp->cc > hn->cc)
				{
					hn->next = tmp->next;
					tmp->next = hn;
					break;
				}
				tmp = tmp->next;
			}
		}
		if(tmp == NULL)
		{
			lq->next = hn;
			lq = lq->next;
		}
	}
	return 0;
}

int BBTSP(int v[])
{//解旅行售货员问题的优先队列式分支限界法

	/*初始化最优队列的头结点*/
	head = (MinHeapNode*)malloc(sizeof(MinHeapNode));
	head->cc = 0;
	head->x = 0;
	head->lcost = 0;
	head->next = NULL;
	head->rcost = 0;
	head->s = 0;
	int *MinOut = new int[n + 1]; /*定义定点i的最小出边费用*/
	//计算MinOut[i]=顶点i的最小出边费用
	int MinSum = 0;//最小出边费用总合
	for(int i = 1; i <= n; i++)
	{
		int Min = NoEdge; /*定义当前最小值*/
		for(int j = 1; j <= n; j++)
			if(a[i][j] != NoEdge && /*当定点i,j之间存在回路时*/
				(a[i][j] < Min || Min == NoEdge)) /*当顶点i,j之间的距离小于Min*/
				Min = a[i][j]; /*更新当前最小值*/
		if(Min == NoEdge)
			return NoEdge;//无回路
		MinOut[i] = Min;
		//printf("%d\n",MinOut[i]);/*顶点i的最小出边费用*/
		MinSum += Min;
		// printf("%d\n",MinSum); /*最小出边费用的总和*/
	}


	MinHeapNode *E = 0;
	E = (MinHeapNode*)malloc(sizeof(MinHeapNode));
	E->x = new int[n];
	// E.x=new int[n];
	for(int i = 0; i < n; i++)
		E->x[i] = i + 1;
	E->s = 0;
	E->cc = 0;
	E->rcost = MinSum;
	E->next = 0; //初始化当前扩展节点
	int bestc = NoEdge; /*记录当前最小值*/
	//搜索排列空间树
	while(E->s < n - 1)
	{//非叶结点
		if(E->s == n - 2)
		{//当前扩展结点是叶结点的父结点
			/*
			首先考虑s=n-2的情形,此时当前扩展结点是排列树中某个叶结点的父结点。如果该叶结点相应一条可行回路
			且费用小于当前最小费用,则将该叶结点插入到优先队列中,否则舍去该叶结点
			*/
			if(a[E->x[n - 2]][E->x[n - 1]] != NoEdge && /*当前要扩展和叶节点有边存在*/
				a[E->x[n - 1]][1] != NoEdge && /*当前页节点有回路*/
				(E->cc + a[E->x[n - 2]][E->x[n - 1]] + a[E->x[n - 1]][1] < bestc /*该节点相应费用小于最小费用*/
				|| bestc == NoEdge))
			{
				bestc = E->cc + a[E->x[n - 2]][E->x[n - 1]] + a[E->x[n - 1]][1]; /*更新当前最新费用*/
				E->cc = bestc;
				E->lcost = bestc;
				E->s++;
				E->next = NULL;
				Insert(E); /*将该页节点插入到优先队列中*/
			}else
				free(E->x);//该页节点不满足条件舍弃扩展结点 
		}else
		{/*产生当前扩展结点的儿子结点
		 当s<n-2时,算法依次产生当前扩展结点的所有儿子结点。由于当前扩展结点所相应的路径是x[0:s],
		 其可行儿子结点是从剩余顶点x[s+1:n-1]中选取的顶点x[i],且(x[s],x[i])是所给有向图G中的一条边。
		 对于当前扩展结点的每一个可行儿子结点,计算出其前缀(x[0:s],x[i])的费用cc和相应的下界lcost。
		 当lcost<bestc时,将这个可行儿子结点插入到活结点优先队列中。*/
			for(int i = E->s + 1; i < n; i++)
				if(a[E->x[E->s]][E->x[i]] != NoEdge)
				{ /*当前扩展节点到其他节点有边存在*/
					//可行儿子结点
					int cc = E->cc + a[E->x[E->s]][E->x[i]]; /*加上节点i后当前节点路径*/
					int rcost = E->rcost - MinOut[E->x[E->s]]; /*剩余节点的和*/
					int b = cc + rcost; //下界
					if(b < bestc || bestc == NoEdge)
					{//子树可能含最优解,结点插入最小堆
						MinHeapNode * N;
						N = (MinHeapNode*)malloc(sizeof(MinHeapNode));
						N->x = new int[n];
						for(int j = 0; j < n; j++)
							N->x[j] = E->x[j];
						N->x[E->s + 1] = E->x[i];
						N->x[i] = E->x[E->s + 1];/*添加当前路径*/
						N->cc = cc; /*更新当前路径距离*/
						N->s = E->s + 1; /*更新当前节点*/
						N->lcost = b; /*更新当前下界*/
						N->rcost = rcost;
						N->next = NULL;
						Insert(N); /*将这个可行儿子结点插入到活结点优先队列中*/
					}
				}
				free(E->x);
		}//完成结点扩展
		DeleteMin(E);//取下一扩展结点
		if(E == NULL)
			break; //堆已空

	}
	if(bestc == NoEdge)
		return NoEdge;//无回路
	for(int i = 0; i < n; i++)
		v[i + 1] = E->x[i];//将最优解复制到v[1:n]
	while(true)
	{//释放最小堆中所有结点
		free(E->x);
		DeleteMin(E);
		if(E == NULL)
			break;
	}
	return bestc;
}

int main()
{
	n = 0;
	int i = 0;
	//FILE *in, *out;
	//in = fopen("input.txt", "r");
	//out = fopen("output.txt", "w");
	//if(in == NULL || out == NULL)
	//{
	//	printf("没有输入输出文件\n");
	//	return 1;
	//}
	//fscanf(in, "%d", &n);
	n=5;
	a = (int**)malloc(sizeof(int*) * (n + 1));
	for(i = 1; i <= n; i++)
	{
		a[i] = (int*)malloc(sizeof(int) * (n + 1));
	}
// 	for(i = 1; i <= n; i++)
// 		for(int j = 1; j <= n; j++)
// 			//fscanf(in, "%d", &a[i][j]);
// 			a[i][j]=1;
	a[1][1]=0;
	a[1][2]=5;
	a[1][3]=8;
	a[1][4]=5;
	a[1][5]=4;

	a[2][1]=5;
	a[2][2]=0;
	a[2][3]=5;
	a[2][4]=6;
	a[2][5]=3;

	a[3][1]=8;
	a[3][2]=5;
	a[3][3]=0;
	a[3][4]=5;
	a[3][5]=4;

	a[4][1]=5;
	a[4][2]=6;
	a[4][3]=6;
	a[4][4]=0;
	a[4][5]=3;

	a[5][1]=4;
	a[5][2]=3;
	a[5][3]=4;
	a[5][4]=3;
	a[5][5]=0;

	// prev = (int*)malloc(sizeof(int)*(n+1)) ;
	int*v = (int*)malloc(sizeof(int) * (n + 1));// MaxLoading(w , c , n) ;
	for(i = 1; i <= n; i++)
		v[i] = 0;
	bestc = BBTSP(v);

	printf("\n");
	for(i = 1; i <= n; i++)
		fprintf(stdout, "%d\t", v[i]);
	fprintf(stdout, "\n");
	fprintf(stdout, "%d\n", bestc);
	return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.

2.输出结果

1->2->5->3->4->1
距离:22
  • 1.
  • 2.