题解
题目大意 给你n-1条带权边组成一个n个节点的树 题目没给n接收到文件尾 求这个树的直径 树的直径为树中两个距离最远点的距离
方法1 两次BFS
第一次任找一点为起点进行BFS得到最远的点p 点p一定为直径上的一个端点
第二次以p为起点再次BFS得到最远的点q 并求出pq之间的距离即为树的直径
AC代码
#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e4 + 10;
struct node
{
int v, w;
node(int a = 0, int b = 0) : v(a), w(b) {}
};
vector<node> e[MAXN];
int vis[MAXN];
node BFS(int x) //返回最远节点和最远距离
{
node res; //结果
queue<node> q;
q.push(node(x, 0));
vis[x] = 1;
while (!q.empty())
{
int u = q.front().v, c = q.front().w;
q.pop();
for (int i = 0; i < e[u].size(); i++)
{
int v = e[u][i].v, w = e[u][i].w;
if (!vis[v])
{
vis[v] = 1;
q.push(node(v, c + w));
if (res.w < c + w) //更新结果
res = node(v, c + w);
}
}
}
return res;
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int u, v, w;
while (scanf("%d%d%d", &u, &v, &w) != EOF)
e[u].push_back(node(v, w)), e[v].push_back(node(u, w));
int p = BFS(1).v; //随意选取一点找到最远点p
memset(vis, 0, sizeof(vis));
cout << BFS(p).w << endl; //再从p找到最远点q则pq为树的直径
return 0;
}
方法2 树形dp
d[i]表示从i到叶子节点的最长路径 p[i]表示经过i的最长路径
d[i]在DFS回溯后通过叶子节点转移 即d[i] = max(d[i], d[j] + i到j距离)
p[i]为两个子节点到叶子节点的距离+到两个子节点的距离 如果使用双重循环jk会导致超时 在更新d[i]之前更新p[i]
p[i] = max(p[i], d[i] + d[k] + i到k距离) d[i]表示着到k以前的子节点的叶子最大距离再加上d[k]和到k的距离
AC代码
#include <stdio.h>
#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e4 + 10;
int d[MAXN], p[MAXN]; //d[i]从i到叶子节点的最长路径 p[i]经过i的最长路径
int ans;
struct node
{
int v, w;
node(int a = 0, int b = 0) : v(a), w(b) {}
};
vector<node> e[MAXN];
void DFS(int x, int f)
{
for (int i = 0; i < e[x].size(); i++)
{
int y = e[x][i].v, z = e[x][i].w;
if (y != f)
{
DFS(y, x);
//最长路径等于两个子节点到叶子节点的距离+到两个子节点的距离 这里不使用双重循环求最大值
p[x] = max(p[x], d[x] + d[y] + z); //d[x]表示着i-1的最优答案和选择i子节点的长度和
d[x] = max(d[x], d[y] + z); //子节点+到子节点长度
}
}
ans = max(ans, p[x]);
}
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int u, v, w;
while (scanf("%d%d%d", &u, &v, &w) != EOF)
e[u].push_back(node(v, w)), e[v].push_back(node(u, w));
DFS(1, 0); //任取一点作为根
cout << ans << endl;
return 0;
}