树的直径:假设 s-t这条路径为树的直径,或者称为树上的最长路
现有结论,从任意一点u出发搜到的最远的点一定是s、t中的一点,然后在从这个最远点开始搜,就可以搜到另一个最长路的端点。即用两遍搜索就可以找出树的最长路。
题目链接:
http://www.lightoj.com/volume_showproblem.php?problem=1094
题意:树的节点间,路径间边的权值和最大是多少
代码:
#include <iostream>
#include <stdio.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <string.h>
#include <queue>
#include <sstream>
#include <math.h>
#include <stdlib.h>
#include <functional>
#include <vector>
#include <string.h>
using namespace std;
int n, m;
vector<pair <int, int> > g[30100];
bool vis[30100];
int in[30010], weight[30010], dis[30010];
int ans, pos;
void bfs(int u)
{
queue<int> que;
while (!que.empty()) que.pop();
que.push(u);
dis[u] = 0;
vis[u] = true;
int tmp = 0;
while (!que.empty())
{
int v = que.front();
que.pop();
for (int i = 0;i < g[v].size();i++)
{
int t = g[v][i].first;
int w = g[v][i].second;
if (!vis[t])
{
vis[t] = true;
dis[t] = dis[v] + w;
if (dis[t] > tmp)
{
tmp = dis[t];
pos = t;
}
que.push(t);
}
}
}
}
void dfs(int u, int sum)
{
vis[u] = true;
ans = max(ans, sum);
for (int i = 0;i < g[u].size();i++)
{
int v = g[u][i].first;
int w = g[u][i].second;
if (!vis[v]) dfs(v, sum + w);
}
}
int main()
{
int t, cases = 1;
scanf("%d",&t);
while (t--)
{
memset(dis, 0, sizeof(dis));
scanf("%d", &n);
int u, v, w;
for (int i = 0;i <= n;i++) g[i].clear();
for (int i = 1;i < n;i ++ )
{
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(make_pair(v, w));
g[v].push_back(make_pair(u, w));
}
memset(vis, false, sizeof(vis));
bfs(0);
ans = 0;
memset(vis, false, sizeof(vis));
dfs(pos, 0);
printf("Case %d: %d\n",cases++, ans);
}
return 0;
}