树的直径

求一棵树上距离最远的两个顶点的距离,就是求树的直径。做法是两次BFS或DFS。设r是树T的根,u是距离r最远的结点,v是距离u最远的结点。则树的直径就是d(u , v)。
可以用反证法证明:http://wenku.baidu.com/view/00d9168984868762caaed5a4.html (图的直径可以用Floyd做:http://blog.csdn.net/sunmenggmail/article/details/7739419
下面是一个DFS实现,里面用无向图(就是对称的有向图)来表示树,所以很方便从任何一个点DFS。做完DFS,返回节点号就行了。两次调用完,ans_path里记录的就是直径。有道POJ的习题有空可以练一下:http://poj.org/problem?id=1985

在需要很多次调用DFS的情况下,多次memset visited[N]会耗费许多时间(因为N很大),可以加个变量visited_id,每次DFS,visited_id++,然后判断visited[N] == visited_id就行了。

#include <vector>;
using namespace std;

const static int N = 200003;
bool visited[N];
vector<int> curr_path;
vector<int> ans_path;
void dfs_helper(vector<vector<int>> &tree, int root, vector<int> &curr, vector<int> &ans) {
	if (visited[root]) {
		return;
	}
	visited[root] = true;
	curr.push_back(root);
	if (curr.size() > ans.size()) {
		ans = curr; // vector copy, but most d times, d is the length of the diameter
	}
	int m = tree[root].size();
	for (int i = 0; i < m; i++) {
		dfs_helper(tree, tree[root][i], curr, ans);
	}
	curr.pop_back();
}

int dfs(vector<vector<int>> &tree, int root) {
	curr_path.clear();
	ans_path.clear();
	memset(visited, false, sizeof(visited));
	dfs_helper(tree, root, curr_path, ans_path);
	return ans_path.back();
}

int main()
{
	// int root = dfs(tree, 0);
	// dfs(tree, root);
	// then the ans_path is the shortest path in the tree
}
原文地址:https://www.cnblogs.com/lautsie/p/3367288.html