题意:给定一棵树中,让你计算它的直径,也就是两点间的最大距离。
析:就是一个树上DP,用两次BFS或都一次DFS就可以搞定。但两次的时间是一样的。
代码如下:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; vector<int> G[maxn]; int f[maxn], g[maxn], l[maxn]; int dfs(int root, int fa){ if(f[root] != -1) return f[root]; if(!G[root].size()) return f[root] = 0; int ans = root, m = 0, mm = 0; for(int i = 0; i < G[root].size(); ++i){ int u = G[root][i]; if(u == fa) continue; if(dfs(u, root) + 1 > m){ m = f[u] + 1; ans = u; } } l[root] = ans; for(int i = 0; i < G[root].size(); ++i){ int u = G[root][i]; if(f[u] + 1 > mm && u != l[root]) mm = f[u] + 1; } g[root] = mm; return f[root] = m; } int main(){ int n, m, u, v; cin >> n >> m; while(m--){ scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u); } memset(f, -1, sizeof(f)); int ans = 0; for(int i = 1; i <= n; ++i) if(f[i] == -1) dfs(i, -1); for(int i = 1; i <= n; ++i) ans = max(ans, f[i]+g[i]); cout << ans << endl; return 0; }
两次BFS:
#include<bits/stdc++.h> using namespace std; const int maxn = 1e5 + 5; int d[maxn]; vector<int> G[maxn]; int vis[maxn], vvis[maxn]; int bfs(int root){ memset(vis, 0, sizeof(vis)); memset(d, 0, sizeof(d)); vis[root] = 1; vvis[root] = 1; queue<int> q; q.push(root); int ans = root, mmax = 0; while(!q.empty()){ root = q.front(); q.pop(); for(int i = 0; i < G[root].size(); ++i){ int u = G[root][i]; if(vis[u]) continue; q.push(u); vis[u] = vvis[u] = 1; d[u] = d[root] + 1; if(mmax < d[u]){ mmax = d[u]; ans = u; } } } return ans; } int solve(int root){ int u = bfs(root); int v = bfs(u); return d[v]; } int main(){ int n, m, u, v; cin >> n >> m; for(int i = 0; i < m; ++i){ scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u); } memset(vvis, 0, sizeof(vvis)); int ans = 0; for(int i = 1; i <= n; ++i) if(!vvis[i]) ans = max(ans, solve(i)); cout << ans << endl; return 0; }