求树的直径 树的直径是指树的最长简单路。求法: 两遍BFS :先任选一个起点BFS找到最长路的终点,再从终点进行BFS,则第二次BFS找到的最长路即为树的直径; 原理: 设起点为u,第一次BFS找到的终点v一定是树的直径的一个端点 证明: 1) 如果u 是直径上的点,则v显然是直径的终点(因为如果v不是的话,则必定存在另一个点w使得u到w的距离更长,则于BFS找到了v矛盾) 2) 如果u不是直径上的点,则u到v必然于树的直径相交(反证),那么交点到v 必然就是直径的后半段了 所以v一定是直径的一个端点,所以从v进行BFS得到的一定是直径长度 相关题目有TOJ1056,TOJ3517. TOJ 1056(Labyrinth): 大意是一个由‘#’和'.'构成的迷宫,'.'表示可行,‘#’表示不可行,问可行的最长的路的长度是多少。 view plaincopy to clipboardprint? include <cstdio> #include <cstring> #include <queue> #define M 1002 using namespace std; int r,c; char map[M][M]; bool flag[M][M]; int move[4][2]={-1,0,1,0,0,-1,0,1}; // 分别表示上下左右 int maxt; struct Node{ int x,y,num; }; Node ans; bool legal(int x,int y){ //判断该点是否越界及是否可走 if(x >=0 && x < r && y>=0 && y < c &&map[x][y]=='.') return true; return false; } void bfs(Node start){ memset(flag,false,sizeof(flag)); //初始所有点标记为false flag[start.x][start.y] = true; //起点标记为true queue<Node>f; while(!f.empty()) f.pop(); //清空创建的队列 Node m,n,tep; int tx,ty,xx,yy; int i,j,k,num; f.push(start); while(!f.empty()){ //如果队列不为空 m = f.front(); //取出队首元素 tx = m.x; ty = m.y; num = m.num; if(num > maxt){ //如果该元素的长度大于maxt,更新maxt maxt = num; ans = m; } for(i = 0;i < 4; i++){ //以m为起点向4个方向BFS xx = tx + move[i][0]; yy = ty + move[i][1]; if(!flag[xx][yy] && legal(xx,yy)){ flag[xx][yy] = true; tep.x = xx; tep.y = yy; tep.num = num + 1; f.push(tep); if(num+1>maxt){ //如果有更大的则更新 maxt = num + 1; ans = tep; } } } f.pop(); //弹出队首元素 } } int main(){ int i,j,T; Node start,end; bool mark; scanf("%d",&T); while(T--){ scanf("%d%d",&c,&r); mark = false; maxt = -1; for(i = 0;i < r; i++) scanf("%s",map[i]); for(i = 0;i < r; i++){ for(j = 0;j < c; j++){ if(map[i][j]=='.'){ //任选一点BFS start.x = i; start.y = j; start.num = 0; bfs(start); mark = true; break; } } if(mark) break; } maxt = -1;ans.num = 0; //此时ans一定是直径的端点,将它设为起点 bfs(ans); //进行第二次BFS printf("Maximum rope length is %d. ",maxt); } } TOJ3517(The longest athletic track): 题目给出了一棵生成树,问这棵生成树最长的路的长度是多少。 view plaincopy to clipboardprint? #include<iostream> #include<queue> #define INF 999999 #define M 2002 using namespace std; int n; int maxx; int map[M][M],sum[M]; bool flag[M]; int bfs(int begin){ queue<int>f; int i,m,k,key; maxx=0; memset(flag,false,sizeof(flag)); f.push(begin); while(!f.empty()){ k=f.front(); for(i=1;i<=n;i++){ if(map[k][i]!=INF&&!flag[i]){ flag[i]=true; f.push(i); sum[i]=sum[k]+map[k][i]; if(sum[i]>maxx) { maxx=sum[i];key=i; } } } f.pop(); } return key; } int main() { int i,j,k,dis,key,cas; scanf("%d",&cas); while(cas--){ scanf("%d",&n); for(i=1;i<n;i++) for(j=i+1;j<=n;j++) map[i][j]=map[j][i]=INF; for(i=1;i<n;i++){ scanf("%d%d%d",&j,&k,&dis); map[j][k]=map[k][j]=dis; } sum[1]=0; key=bfs(1); sum[key]=0; key=bfs(key); printf("%d ",maxx); } //system("pause"); }