sgu149: Computer Network

题目大意:给你一棵树,求任意两点间的最长距离。
输入:
第一行一个数 n ,表示树的节点数。
以后 n1 行每行两个数 a,b 表示 i 的父亲是 a,他们之间的边权为 b

fi表示以 i 节点为根的子树到i的最大距离。
gi表示以 i 节点为根的子树到i的次大距离。
hi表示 i 节点到树中去掉以i节点为根的子树的部分的最大距离。
说白了,f,g就是向下走, h <script type="math/tex" id="MathJax-Element-2680">h</script>就是先向上走,再向下走。
状态转移请自行脑补。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mp make_pair
#define X first
#define Y second
using namespace std;
typedef pair<int, int> pii;

inline int read()
{
    int x = 0, f = 1, t = getchar();
    while(t < '0' || t > '9') t == '-' ? f = -1 : 0, t = getchar();
    while(t >= '0' && t <= '9') x = (x<<1) + (x<<3) + t-'0', t = getchar();
    return x * f;
}

const int maxn = 10005;
const int maxm = 20005;
struct Edge
{
    int u, v, w;
    Edge(int u = 0, int v = 0, int w = 0): u(u), v(v), w(w) {}
};

int n, m;
int head[maxn], next[maxm], h[maxn];
Edge edge[maxm];
pii f[maxn], g[maxn], tmp;

inline void relax(int &x, int y)
{
    y > x ? x = y : 0;
}
inline void adde(int a, int b, int c)
{
    edge[m] = Edge(a, b, c), next[m] = head[a], head[a] = m++;
}
inline void addedge(int c, int b, int a)
{
    adde(a, b, c), adde(b, a, c);
}
void init()
{
    memset(head, -1, sizeof(head));
    n = read(), m = 0;
    for(int i = 2; i <= n; ++i)
        addedge(read(), i, read());
}
void solve1(int x, int p)
{
    for(int i = head[x]; i != -1; i = next[i])
    {
        Edge &e = edge[i];
        if(e.v != p)
        {
            solve1(e.v, x);
            tmp = mp(f[e.v].X + e.w, e.v);
            if(tmp.X > f[x].X) g[x] = f[x], f[x] = tmp;
            else if(tmp.X > g[x].X) g[x] = tmp;
        }
    }
}
void solve2(int x, int p)
{
    for(int i = head[x]; i != -1; i = next[i])
    {
        Edge &e = edge[i];
        if(e.v != p)
        {
            if(f[x].Y == e.v) relax(h[e.v], g[x].X + e.w);
            else relax(h[e.v], f[x].X + e.w);
            relax(h[e.v], h[x] + e.w);
            solve2(e.v, x);  
        }
    }
}
void work()
{
    solve1(1, 0);
    solve2(1, 0);
    for(int i = 1; i <= n; ++i)
        printf("%d\n", max(f[i].X, h[i]));
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif

    init();
    work();

    #ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    #endif
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值