樹的直徑(轉發自CSDN)


求樹的直徑
樹的直徑是指樹的最長簡單路。求法: 兩遍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.\n",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\n",maxx);  
             }  
    //system("pause");  
}  

 


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: