链接:
http://poj.org/problem?id=1985
题意:
有 个农场和 条路,以及每条路的方向(方向在这道题中没有用)。并且每对农场之间只有一条路可达,即这是一个树。求最长的一条路,也就是两点间的最大距离,即树的直径。
思路:
树的直径: 树的最长简单路(树中所有路径的最大值)。
求解方法: 跑两遍 BFS。第一遍 BFS 先任选一个起点,BFS 找到最长路的终点。第二遍 BFS 再从第一遍找到的终点出发进行 BFS,那么第二次 BFS 找到的最长路即为树的直径。
应用原理: 从树中任一节点 出发,一次 BFS 所到达的节点 一定是树的直径的端点。
原理证明:
AC代码
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN = 40100;
int n, m;
struct edge {
int to, cost;
};
std::vector<edge > T[MAXN];
void add_edge(int u, int v, int w) {
T[u].push_back((edge){v, w});
}
int dis[MAXN];
bool vis[MAXN];
int bfs(int s) {
for (int i = 0; i <= n; ++i) {
dis[i] = 0;
vis[i] = 0;
}
int max_dist=0;
int id=s;
queue<int > q;
q.push(s);
dis[s] = 0;
vis[s] = 1;
while(!q.empty()) {
int now = q.front();
q.pop();
if(dis[now] > max_dist)
max_dist = dis[id=now];
for (int i = 0; i < T[now].size(); ++i) {
int v = T[now][i].to;
int w = T[now][i].cost;
if(!vis[v]) {
vis[v] = 1;
q.push(v);
dis[v] = dis[now] + w;
}
}
}
return id;
}
int main(int argc, char const *argv[])
{
scanf("%d%d", &n, &m);
int f1, f2, l;
string d;
for (int i = 0; i < m; ++i) {
scanf("%d%d%d%*s", &f1, &f2, &l);
add_edge(f1, f2, l);
add_edge(f2, f1, l);
}
printf("%d\n",dis[bfs(bfs(1))]);
return 0;
}