1 条题解

  • 0
    @ 2025-8-24 23:02:58

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar yingxi
    没咋 || 最后在线时间:2025年8月21日10时55分

    搬运于2025-08-24 23:02:58,当前版本为作者最后更新于2025-05-14 15:58:34,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    题目传送门

    题意

    给定一棵有 nn 个节点的树,对于每个节点,都求出离他最远的节点离他的距离。

    思路

    • 暴力:以每个点为起点依次进行 dfs(i, 0),查看从 ii 出发最多走多少步。

    • 二次 dfs 法:第一次 dfs 从下往上搜,第二次 dfs 从上往下搜,具体见代码。

    ACcode:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N = 1e4 + 5;
    vector<pair<int, int> > g[N];
    int dis1[N], dis2[N]; //dis1表示子树的最长路, dis2表示子树的次长路 
    int f[N], son[N]; //son表示子树的最长路的节点编号, f表示子树外的最长路 
    int n;
    void dfs1(int u, int fa)
    {
    	for (auto x : g[u])
    	{
    		int v = x.first, w = x.second;
    		if (v == fa)
    			continue;
    		dfs1(v, u);
    		//回溯过程将子树的信息带回来更新u
    		if (dis1[u] < dis1[v] + w)
    		{
    			dis2[u] = dis1[u]; //先更新次长路
    			dis1[u] = dis1[v] + w;
    			son[u] = v; // 最长路先经过v
    		}
    		else if (dis2[u] < dis1[v] + w)
    			dis2[u] = dis1[v] + w; 
    	}
    	return ;
    }
    void dfs2(int u, int fa)
    {
    	for (auto x : g[u])
    	{
    		int v = x.first, w = x.second;
    		if (v == fa)
    			continue;
    		//在递的过程中更新数据,父亲更新儿子
    		if (son[u] != v) //u的最长路不包含v, 可以直接用 
    			f[v] = max(dis1[u], f[u]) + w;
    		else
    			f[v] = max(dis2[u], f[u]) + w;
    		dfs2(v, u);
    	}
    	return ;
    }
    void solve()
    {
    	for (int i = 1; i <= n; i++)
    		g[i].clear();
    	//多测注意清空 
    	memset(dis1, 0, sizeof dis1);
    	memset(dis2, 0, sizeof dis2);
    	memset(f, 0, sizeof f);
    	for (int i = 2; i <= n; i++) 
    	{
    		int u, v;
    		cin >> u >> v;
    		g[i].push_back({u, v});
    		g[u].push_back({i, v});
    	}
    	dfs1(1, 0); //从下往上dfs
    	dfs2(1, 0); //从上往下dfs
    	for (int i = 1; i <= n; i++)
    		cout << max(dis1[i], f[i]) << "\n";
    	return ;
    }
    signed main()
    {
    	ios::sync_with_stdio(0);
    	cin.tie(0);
    	cout.tie(0);
    	while (cin >> n)
    		solve();
        return 0;
    }
    
    • 1

    信息

    ID
    10128
    时间
    1000ms
    内存
    512MiB
    难度
    3
    标签
    (无)
    递交数
    0
    已通过
    0
    上传者