树的直径是指树上距离最大的两个节点的距离。
思路是两遍BFS,第一遍BFS时,任选一个起点即可,找到最后遍历到的节点,它肯定是直径的一个端点(也就是离根节点最远的点),然后再用一遍BFS遍历回去,最后遍历到的是直径的另外一个端点。同时记录下走的步数,就可以计算出树的直径了。
看下面几个相关的题:
TOJ 1056
原题链接: http://acm.tju.edu.cn/toj/showp.php?pid=1056
题目大意是:有一个矩阵,里边有#和*两种状态,分别表示可以通过和不能通行。求可以通行的点的最大距离。其中,每两个可通行的点都可以有一条路径连接。
思路:首先从最开始的可通行的点出发,使用BFS搜索,找到最远的点。然后从最远的点出发,再次使用BFS,记录下步数,即为所求的最大距离。
代码如下(写代码用了20分钟,找那个t.x t.y的错误用了一个半小时=====================无语,可长记性了)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char a[1005][1005];//存储矩阵
int direction[4][2] = { 0, 1, 0, -1, 1, 0, -1, 0 };
int visited[1005][1005];
int c, r;
int ans; //存储最远的那个点的步数
struct node{
int x, y, step;
node(int xx, int yy, int s){
x = xx; y = yy; step = s;
}
};
node ansnode(0,0,0); //存储最远的那个点
void bfs(int x, int y){
visited[x][y] = 1;
node temp(x, y, 0);
queue<node> q;
q.push(temp);
ans = 0;
ansnode = temp;
while (!q.empty()){
node t = q.front();
if (ans < t.step) { //每次更新
ans = t.step;
ansnode = t;
}
q.pop();
for (int i = 0; i < 4; i++){
int nx = t.x + direction[i][0]; //又一次被坑,大坑!!!是t.x,t.y
int ny = t.y + direction[i][1];//不是x, y
if (nx < r && nx >= 0 && ny < c && ny >= 0 && visited[nx][ny] == 0 && a[nx][ny] == '.'){
visited[nx][ny] = 1;
node tt(nx, ny, t.step + 1);
q.push(tt);
}
}
}
}
int main(){
int n;
cin >> n;
while (n--){
cin >> c >> r;
for (int i = 0; i < r; i++){
for (int j = 0; j < c; j++){
cin >> a[i][j];
}
}
int flag = 0;
int x0 = 0, y0 = 0;
for (int i = 0; i < r; i++){ //找到第一个可以通行的点
for (int j = 0; j < c; j++){ //其实随便找哪个都行
if (a[i][j] == '.'){
flag = 1;
x0 = i; y0 = j;
break;
}
}
if (flag == 1) break;
}
memset(visited, 0, sizeof(visited));
bfs(x0, y0);
memset(visited, 0, sizeof(visited));
bfs(ansnode.x, ansnode.y); //两次BFS
cout << "Maximum rope length is "<< ans << endl;
}
return 0;
}