daimayuan(代码源oj)最长路径(树形dp,无向树换根dp)

简介: daimayuan(代码源oj)最长路径(树形dp,无向树换根dp)

题目传送门

/*********************************************************************
    程序名:
    版权: Joecai
    作者: Joecai
    日期: 2022-04-14 19:16
    说明:
*********************************************************************/
#include <bits/stdc++.h>
using namespace std;
#define x first
#define y second
# define rep(i,be,en) for(int i=be;i<=en;i++)
# define pre(i,be,en) for(int i=be;i>=en;i--)
#define ll long long
#define endl "\n"
#define LOCAL
#define pb push_back
//#define int long long
typedef pair<ll, ll> PII;
#define eb emplace_back
#define sp(i) setprecision(i)
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
int n;
vector<int>g[N];
int  f[N][2][2];//以i为子树的最长路径和第二长路径 和他们的点
int v[N];//v[y] 记录了 y 号点的父亲 x 号点作为它的子树时从里面连上来的到 y 号点的最长路径
void dfs(int i, int fa)
{
  for (auto j : g[i])
  {
    if (j == fa) continue;
    dfs(j, i);
    if (f[j][0][0] + 1 > f[i][0][0])
    {
      f[i][1][0] = f[i][0][0], f[i][1][1] = f[i][0][1], f[i][0][0] = f[j][0][0] + 1, f[i][0][1] = j;
    } else if (f[j][0][0] + 1 > f[i][1][0])
    {
      f[i][1][1] = j, f[i][1][0] = f[j][0][0] + 1;
    }
  }
}
void dfs1(int i, int fa)
{
  for (auto j : g[i])
  {
    if (j == fa) continue;
    if (f[i][0][1] == j)
    {
      v[j] = 1 + max(f[i][1][0], v[i]);
    } else
    {
      v[j] = 1 + max(f[i][0][0], v[i]);
    }
    dfs1(j, i);
  }
}
void solve()
{
  cin >> n;
  for (int i = 1; i <= n - 1; i++)
  {
    int x, y;
    cin >> x >> y;
    g[x].push_back(y);
    g[y].push_back(x);
  }
  dfs(1, 0);
  dfs1(1, 0);
  for (int i = 1; i <= n; i++)
  {
    cout << f[i][1][0] + f[i][0][0] + v[i] - min({f[i][1][0], f[i][0][0], v[i]}) << endl;;
  }
}
signed main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  //#ifdef LOCAL
  //freopen("data.in.txt","r",stdin);
  //freopen("data.out.txt","w",stdout);
  //#endif
  int __ = 1;
  //cin>>__;
  while (__--)
  {
    solve();
  }
  return 0;
}


目录
相关文章
|
7月前
【每日一题Day300】LC2236判断根结点是否等于子结点之和
【每日一题Day300】LC2236判断根结点是否等于子结点之和
36 0
|
7月前
【每日一题Day214】LC1080根到叶路径上的不足节点 | 递归
【每日一题Day214】LC1080根到叶路径上的不足节点 | 递归
51 0
|
7月前
二叉树查找值为x的结点、树的高度、第k层结点个数的代码实现
二叉树查找值为x的结点、树的高度、第k层结点个数的代码实现
【面试必刷TOP101】删除链表的倒数第n个节点 & 两个链表的第一个公共结点
【面试必刷TOP101】删除链表的倒数第n个节点 & 两个链表的第一个公共结点
55 0
代码随想录Day15 二叉树 LeetCodeT513 找树左下角的值 T112路径总和 T106 从中序和后序遍历构造二叉树
代码随想录Day15 二叉树 LeetCodeT513 找树左下角的值 T112路径总和 T106 从中序和后序遍历构造二叉树
44 0
|
7月前
【每日一题Day367】LC117填充每个节点的下一个右侧节点指针II | BFS
【每日一题Day367】LC117填充每个节点的下一个右侧节点指针II | BFS
47 1
|
测试技术
华为机试HJ48:从单向链表中删除指定值的节点
华为机试HJ48:从单向链表中删除指定值的节点
每日一题---24. 两两交换链表中的节点[力扣][Go]
每日一题---24. 两两交换链表中的节点[力扣][Go]
每日一题---24. 两两交换链表中的节点[力扣][Go]
代码随想录刷题|LeetCode 513. 找树左下角的值 112. 路径总和 113.路径总和|| 106. 从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
代码随想录刷题|LeetCode 513. 找树左下角的值 112. 路径总和 113.路径总和|| 106. 从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
代码随想录刷题|LeetCode 513. 找树左下角的值 112. 路径总和 113.路径总和|| 106. 从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
|
存储 C++
【力扣·每日一题】689. 三个无重叠子数组的最大和 (C++ 前缀和优化dp 保存路径)
【力扣·每日一题】689. 三个无重叠子数组的最大和 (C++ 前缀和优化dp 保存路径)
110 0
【力扣·每日一题】689. 三个无重叠子数组的最大和 (C++ 前缀和优化dp 保存路径)