标签:
问题分析:
树中的路径,即是从树上的某个节点起,经过某个转折节点,到达另一个节点这样一条路径。而最长路径就是要找出这些路径中最长的那一条。
算法思路:
对于每个节点,记录下以该节点为根节点的子树中从该节点开始到所有叶子节点的路径中最长的那一条路径长度d1以及次长的那一条路径长度d2(最长和次长两条路径无公共边)。那么对于我们想要解决的问题(树中的最长路径),就只需要枚举每个节点作为转折节点,求出所有d1+d2中的最大值。
关于d1,d2的求解:
对于任意一个节点,其d1值等于其所有子节点最大d1值加1,其d2值等于其除d1值对应的子节点以外的所有子节点最大d1值加1。
特别的,叶子节点d1=d2=0,对于只有一个儿子的节点,d2=0。
我的代码:
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <cstring> 5 6 using namespace std; 7 8 #define MAXN 100005 9 10 struct Tree 11 { 12 vector<int> v[MAXN]; 13 bool vis[MAXN]; 14 int n, d1[MAXN], d2[MAXN], fa[MAXN]; 15 void init(int _n) 16 { 17 n = _n; 18 for(int i=1; i<=n; ++i) v[i].clear(); 19 memset(&d1[1], 0, n*sizeof(int)); 20 memset(&d2[1], 0, n*sizeof(int)); 21 } 22 void addEdge(int a, int b) 23 { 24 v[a].push_back(b); 25 v[b].push_back(a); 26 } 27 void getFather(int x, int f) 28 { 29 fa[x] = f; 30 vis[x] = true; 31 for(int i=0; i<v[x].size(); ++i) 32 if(!vis[v[x][i]]) getFather(v[x][i], x); 33 } 34 void post_order(int x) 35 { 36 vis[x] = true; 37 for(int i=0; i<v[x].size(); ++i) 38 if(!vis[v[x][i]]) post_order(v[x][i]); 39 int tmp; 40 for(int i=0; i<v[x].size(); ++i) 41 { 42 if(v[x][i]!=fa[x]&&d1[x]<d1[v[x][i]]+1) 43 { 44 d1[x] = d1[v[x][i]]+1; 45 tmp = v[x][i]; 46 } 47 } 48 for(int i=0; i<v[x].size(); ++i) 49 if(v[x][i]!=fa[x]&&v[x][i]!=tmp&&d2[x]<d1[v[x][i]]+1) 50 d2[x] = d1[v[x][i]]+1; 51 } 52 int getAns() 53 { 54 int ans = 0; 55 for(int i=1; i<=n; ++i) ans = max(ans, d1[i]+d2[i]); 56 return ans; 57 } 58 }tree; 59 60 int main() 61 { 62 int n, a, b; 63 while(cin>>n) 64 { 65 tree.init(n); 66 for(int i=0; i<n-1; ++i) 67 { 68 cin>>a>>b; 69 tree.addEdge(a, b); 70 } 71 memset(&tree.vis[1], 0, n); 72 tree.getFather(1, -1); 73 memset(&tree.vis[1], 0, n); 74 tree.post_order(1); 75 cout<<tree.getAns()<<endl; 76 } 77 78 return 0; 79 }
题目来源:http://hihocoder.com/problemset/problem/1050
标签:
原文地址:http://www.cnblogs.com/pczhou/p/4296481.html