(转)求树的直径

树的直径是指树的最长简单路。求法: 两遍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):
        大意是一个由‘#’和'.'构成的迷宫,'.'表示可行,‘#’表示不可行,问可行的最长的路的长度是多少。

  1. include <cstdio>  
  2. #include <cstring>  
  3. #include <queue>  
  4. #define M 1002  
  5. using namespace std;  
  6. int r,c;  
  7. char map[M][M];  
  8. bool flag[M][M];  
  9. int move[4][2]={-1,0,1,0,0,-1,0,1};                                               // 分别表示上下左右  
  10. int maxt;  
  11. struct Node{  
  12.         int x,y,num;  
  13. };  
  14. Node ans;  
  15. bool legal(int x,int y){                                                                   //判断该点是否越界及是否可走  
  16.         if(x >=0 && x < r && y>=0 && y < c &&map[x][y]=='.'return true;  
  17.         return false;  
  18. }  
  19. void bfs(Node start){  
  20.         memset(flag,false,sizeof(flag));                                               //初始所有点标记为false  
  21.         flag[start.x][start.y] = true;                                                    //起点标记为true  
  22.         queue<Node>f;  
  23.         while(!f.empty()) f.pop();                                                       //清空创建的队列  
  24.         Node m,n,tep;  
  25.         int tx,ty,xx,yy;  
  26.         int i,j,k,num;  
  27.         f.push(start);  
  28.         while(!f.empty()){                                                                   //如果队列不为空  
  29.                 m = f.front();                                                                   //取出队首元素  
  30.                 tx = m.x; ty = m.y; num = m.num;  
  31.                 if(num > maxt){                                                              //如果该元素的长度大于maxt,更新maxt  
  32.                         maxt = num;  
  33.                         ans = m;  
  34.                 }  
  35.                 for(i = 0;i < 4; i++){                                                       //以m为起点向4个方向BFS  
  36.                         xx = tx + move[i][0];  
  37.                         yy = ty + move[i][1];  
  38.                         if(!flag[xx][yy] && legal(xx,yy)){  
  39.                                 flag[xx][yy] = true;  
  40.                                 tep.x = xx;  
  41.                                 tep.y = yy;  
  42.                                 tep.num = num + 1;  
  43.                                 f.push(tep);  
  44.                                 if(num+1>maxt){                                            //如果有更大的则更新  
  45.                                         maxt = num + 1;  
  46.                                         ans = tep;  
  47.                                 }  
  48.                         }  
  49.                 }  
  50.                 f.pop();                                                                               //弹出队首元素  
  51.         }   
  52. }  
  53. int main(){  
  54.         int i,j,T;  
  55.         Node start,end;  
  56.         bool mark;  
  57.         scanf("%d",&T);  
  58.         while(T--){  
  59.                 scanf("%d%d",&c,&r);  
  60.                 mark = false; maxt = -1;  
  61.                 for(i = 0;i < r; i++)  
  62.                         scanf("%s",map[i]);  
  63.                 for(i = 0;i < r; i++){  
  64.                         for(j = 0;j < c; j++){  
  65.                                 if(map[i][j]=='.'){                                                     //任选一点BFS  
  66.                                         start.x = i;  
  67.                                         start.y = j;  
  68.                                         start.num = 0;  
  69.                                         bfs(start);  
  70.                                         mark = true;  
  71.                                         break;  
  72.                                 }  
  73.                         }  
  74.                         if(mark) break;  
  75.                 }  
  76.                 maxt = -1;ans.num = 0;                                                           //此时ans一定是直径的端点,将它设为起点  
  77.                 bfs(ans);                                                                                    //进行第二次BFS  
  78.                 printf("Maximum rope length is %d.\n",maxt);  
  79.         }  
  80. }  
 

 

TOJ3517(The longest athletic track):
          题目给出了一棵生成树,问这棵生成树最长的路的长度是多少。

  1. #include<iostream>  
  2. #include<queue>  
  3. #define INF 999999  
  4. #define M 2002  
  5. using namespace std;  
  6. int n;  
  7. int maxx;  
  8. int map[M][M],sum[M];  
  9. bool flag[M];  
  10. int bfs(int begin){  
  11.             queue<int>f;  
  12.             int i,m,k,key;  
  13.             maxx=0;  
  14.             memset(flag,false,sizeof(flag));  
  15.             f.push(begin);  
  16.             while(!f.empty()){  
  17.                         k=f.front();  
  18.                          for(i=1;i<=n;i++){  
  19.                                  if(map[k][i]!=INF&&!flag[i]){  
  20.                                             flag[i]=true;  
  21.                                             f.push(i);  
  22.                                             sum[i]=sum[k]+map[k][i];  
  23.                                              if(sum[i]>maxx) { maxx=sum[i];key=i; }  
  24.                                  }  
  25.                          }  
  26.                          f.pop();  
  27.             }  
  28.             return key;  
  29. }  
  30. int main()  
  31. {  
  32.             int i,j,k,dis,key,cas;  
  33.             scanf("%d",&cas);  
  34.             while(cas--){  
  35.                          scanf("%d",&n);  
  36.                          for(i=1;i<n;i++)  
  37.                                    for(j=i+1;j<=n;j++)  
  38.                                             map[i][j]=map[j][i]=INF;  
  39.                          for(i=1;i<n;i++){  
  40.                                    scanf("%d%d%d",&j,&k,&dis);  
  41.                                    map[j][k]=map[k][j]=dis;  
  42.                          }  
  43.                          sum[1]=0;  
  44.                          key=bfs(1);  
  45.                          sum[key]=0;  
  46.                          key=bfs(key);  
  47.                          printf("%d\n",maxx);  
  48.              }  
  49.     //system("pause");  
  50. }  

 

posted @ 2010-10-23 09:27  elite_lcf  阅读(8871)  评论(0编辑  收藏  举报
知识共享许可协议
本博客采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。