HDU 2196 Computer

http://acm.hdu.edu.cn/showproblem.php?pid=2196

题意:

给出一棵树,求出每个点到其他点的最远距离。

 

思路:
对于每一个点,一方面它可以往它的子树方向走,另一方面可以往父亲结点的方向走。所以我们需要两次dfs,第一次用来求出每个点往其子树方向的最远距离和次远距离,为什么要计算出次远距离呢,因为在第二次dfs求父亲结点方向时,可能父亲结点的最大值经过了这个点,此时需要更换路线使得它不经过这个点。

#include<iostream> 
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;

#define N 10001

int n;

struct node
{
    int to;    //终点
    int next;  //下一条同样起点的边
    int w;     //权值
}edge[N*2];

int tol;
int head[N];  //头结点,邻接链表存储

int dist[N][3];   //dist[N][0]代表正向最远距离,[N][1]代表正向次远距离,[N][2]代表反向最远距离
int flag[N];

//邻接链表存储,加入到链表的首部
void add_edge(int u, int v, int w)
{
    edge[tol].to = v;
    edge[tol].w = w;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].w = w;
    edge[tol].next = head[v];
    head[v] = tol++;
}


int dfs1(int u, int fa)
{
    if (dist[u][0] != -1)  return dist[u][0];
    dist[u][0] = dist[u][1] = 0;
    
    for (int e = head[u]; e != -1; e = edge[e].next)
    {
        int v = edge[e].to;
        if (v == fa)   continue;
        dfs1(v, u);
        if (dist[u][0] < dist[v][0] + edge[e].w)
        {
            flag[u] = v;
            dist[u][1] = dist[u][0];               //更新次远距离
            dist[u][0] = dist[v][0] + edge[e].w;   //更新最远距离
        }
        //这个不能忘,比最远距离小但可能比次远距离大,此时需要更新次远距离
        else if (dist[u][1] < dist[v][0] + edge[e].w)
            dist[u][1] = dist[v][0] + edge[e].w;
    }
    return dist[u][0];
}


void dfs2(int u, int fa)
{
    for (int e = head[u]; e != -1; e = edge[e].next)
    {
        int v = edge[e].to;
        if (v == fa)  continue;
        if (v == flag[u])  dist[v][2] = max(dist[u][2], dist[u][1]) + edge[e].w;
        else dist[v][2] = max(dist[u][2], dist[u][0]) + edge[e].w;
        dfs2(v, u);
    }
}

int main()
{
    //freopen("D:\\txt.txt", "r", stdin);
    int v, w;
    while (~scanf("%d", &n) && n)
    {
        tol = 0;
        memset(head, -1, sizeof(head));
        memset(dist, -1, sizeof(dist));
        memset(flag, -1, sizeof(flag));
        for (int i = 2; i <= n; i++)
        {
            scanf("%d%d", &v, &w);
            add_edge(i, v, w);    //存边
        }

        dfs1(1, -1);
        dfs2(1, -1);
        for (int i = 1; i <= n; i++)
            printf("%d\n", max(dist[i][0], dist[i][2]));
    }
    return 0;
}

 

posted @ 2017-02-12 20:05  Kayden_Cheung  阅读(135)  评论(0编辑  收藏  举报
//目录