HDU 2196 Computer(树的直径)

输出一棵树上,每个点到最远点的距离

思路:先搜两遍找出树的直径,然后在从这两点出发,每个点距离这两点中距离大的就是最远点距离

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int N = 50005;
int n, m;

struct Edge {
    int v, w;
    Edge() {}
    Edge(int v, int w) {
        this->v = v;
        this->w = w;
    }
} edge[N * 2];

int head[N], nxt[N * 2], en;

void addedge(int u, int v, int w) {
    edge[en] = Edge(v, w);
    nxt[en] = head[u];
    head[u] = en++;
}

typedef long long ll;

ll d[N];
queue<int> Q;

int get(int s) {
    Q.push(s);
    memset(d, -1, sizeof(d));
    d[s] = 0;
    int ans = s;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        if (d[u] > d[ans]) ans = u;
        for (int i = head[u]; i + 1; i = nxt[i]) {
            int v = edge[i].v;
            int w = edge[i].w;
            if (d[v] != -1) continue;
            d[v] = d[u] + w;
            Q.push(v);
        }
    }
    return ans;
}

ll dp[N];

void gao(int s) {
    Q.push(s);
    memset(d, -1, sizeof(d));
    d[s] = 0;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        dp[u] = max(dp[u], d[u]);
        for (int i = head[u]; i + 1; i = nxt[i]) {
            int v = edge[i].v;
            int w = edge[i].w;
            if (d[v] != -1) continue;
            d[v] = d[u] + w;
            Q.push(v);
        }
    }
}

inline void scanf_(int &num)//无负数
{
    char in;
    while((in=getchar()) > '9' || in<'0') ;
    num=in-'0';
    while(in=getchar(),in>='0'&&in<='9')
        num*=10,num+=in-'0';
}

int main() {
    while (~scanf("%d", &n)) {
        en = 0;
        memset(head, -1, sizeof(head));
        int x, y, z;
        for (int i = 2; i <= n; i++) {
            scanf_(y); scanf_(z);
            addedge(i, y, z);
            addedge(y, i, z);
        }
        int s = get(1);
        int e = get(s);
        memset(dp, 0, sizeof(dp));
        gao(s);
        gao(e);
        for (int i = 1; i <= n; i++) printf("%I64d\n", dp[i]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值