[POJ-2631] 求树的直径

本文介绍了一种求解树的直径的有效算法。通过构建边集表示的图,并使用两次广度优先搜索(BFS)找到树中最远的两个顶点,从而确定树的直径。文章还分享了编码过程中的心得,强调了清晰思考的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如何求树的直径我就不说了。

AC此题后有两点感悟:1. 通过边集来存储图(如何查找) 2. 先想清楚再编码,否则会一塌糊涂

/*
 * POJ-2631
 * mike-w
 * 2012-10-10
 * ******************************
 * find the diameter of a tree
 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define MAXSIZE 11111
#define QSIZE 22222
#define INF 9999999
#define xDISP_GRAPH
#define xFOO_DEBUG

int maxn;
int edge[MAXSIZE][3], head[MAXSIZE], lsize;
int que[QSIZE], qhead, qtail, qlen;
int tag[MAXSIZE];

int comp(const void *e1, const void *e2)
{
	return *((int*)e1) - *((int*)e2);
}

int build_graph(void)
{
	int i;
	qsort(edge, lsize, sizeof(int[3]), comp);
	memset(head, -1, sizeof(head));
	head[edge[0][0]]=0;
	for(i=1; i<lsize; i++)
		if(edge[i][0]!=edge[i-1][0])
			head[edge[i][0]]=i;
	head[maxn+1]=lsize;
	return 0;
}

int enque(int x)
{
	que[qtail++]=x;
	qtail%=QSIZE;
	qlen++;
	return 0;
}

int deque(void)
{
	int ret=que[qhead++];
	qhead%=QSIZE;
	qlen--;
	return ret;
}

int bfs(int src)
{
	int i, x;
	memset(tag, 0, sizeof(tag));
	tag[src]=1;
	qhead=qtail=qlen=0;
	enque(src);
	while(qlen>0)
	{
		x=deque();
		for(i=head[x]; edge[i][0]==edge[head[x]][0]; i++)
			if(!tag[edge[i][1]])
			{
				tag[edge[i][1]]=edge[i][2]+tag[x];
				enque(edge[i][1]);
			}
	}
	return 0;
}

int max(int e1, int e2)
{
	return e1>e2?e1:e2;
}

#ifdef DISP_GRAPH
int disp_graph(void)
{
	int i, j;
	puts("*GRAPH+++++++++++++++++++++++++++");
	for(i=0; i<=maxn; i++)
		if(head[i]>=0)
		{
			printf("* %2d +\n", i);
			for(j=head[i]; edge[j][1]==edge[head[i]][1]; j++)
				printf("     |- %2d (len=%2d)\n", edge[j][1], edge[j][2]);
		}
	putchar('\n');
	return 0;
}
#endif

int main(void)
{
	int t1, t2, t3, i, maxl, maxi;

	while(scanf("%d%d%d", &t1, &t2, &t3)!=EOF)
	{
		edge[lsize][0]=t1;
		edge[lsize][1]=t2;
		edge[lsize][2]=t3;
		lsize++;
		edge[lsize][0]=t2;
		edge[lsize][1]=t1;
		edge[lsize][2]=t3;
		lsize++;
		maxn=max(max(t1, t2), maxn);
	}
	build_graph();
#ifdef DISP_GRAPH
	disp_graph();
#endif

	bfs(edge[0][0]);
	maxl=0, maxi=0;
	for(i=0; i<=maxn; i++)
		if(tag[i]>maxl)
			maxl=tag[i], maxi=i;
#ifdef FOO_DEBUG
	printf("one point of the diameter = %d\n", maxi);
#endif

	bfs(maxi);
	maxl=0;
	for(i=0; i<=maxn; i++)
		if(tag[i]>maxl)
			maxl=tag[i], maxi=i;
#ifdef FOO_DEBUG
	printf("the other point of the diameter = %d\n", maxi);
#endif
	printf("%d\n", maxl-1);
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值