SGU 149. Computer Network

时间限制:0.25s

空间限制:4M;

题意:

       给出一颗n(n<=10000)个节点的树,和n-1条边的长度。求出这棵树每个节点到最远节点的距离;

 

 

 

 


Solution:

             对于一个节点,我们可以用DFS,在O(n)的时间内求出它的最远节点的距离.

             显然对于10000个节点,不可能将每一个节点都这样求.

             那么我们来看看,对于一个已经求过的节点我们可以做什么:

                   假设,有节点k,他有子节点p,两者距离为d

                   已经求得它的最远节点距离为dis1,

                   这时对他的子节点p来说,有两种情况:

                        一种是:p在k的与最远节点的路径上.

                                 这时p的最远距离等于max(dis1-d,k的次远距离+d);

                       另一种是:p不在k的最远路径上.

                                  此时p的最远距离等于max(dis1+d,p向下的最远距离);

              通过上面我们发现,我们需要一个节点的最远距离和次远距离以及p向下的最远距离.

              幸运的是这三个量都可以通过一次对根的DFS在O(n)的时间内求出.

              最后再从根进行一次DFS遍求出每个节点的最远距离和次远距离就可以求出所有的答案了.

              总的时间复杂度O(n),空间复杂度O(n);

code

#include <iostream>

#include <cstdio>

#include <vector>

#include <utility>

using namespace std;



#define mp make_pair

#define fi first

#define se second

#define sz(x) ((int) (x).size())

#define rd(a) scanf("%d",&a)

#define rdd(a,b) scanf("%d%d",&a,&b);

#define rep(i,a,b) for(int i=(a);i<=(b);i++)

#define pb push_back



typedef pair<int, int> ii;

typedef vector<ii> vii;

const int INF = 11111;



vii edge[INF];

int dis[INF][2], ans[INF];

int n, x, y;

int dfs (int x) {

	dis[x][0] = 0;

	rep (i, 0, sz(edge[x]) - 1) {

		ii v = edge[x][i];

		int tem = dfs (v.fi)+v.se;

		rep (i, 0, 1)   if (tem > dis[x][i]) swap (tem, dis[x][i]);

	}

	return dis[x][0];

}

void DP (int x) {

	int tem;

	ans[x] = dis[x][0];

	rep (i, 0, sz (edge[x]) - 1) {

		ii v = edge[x][i];

		if (dis[v.fi][0] + v.se == dis[x][0])

			tem = dis[x][1] + v.se;

		else

			tem = dis[x][0] + v.se;

		rep (i, 0, 1) if (tem > dis[v.fi][i]) swap (tem, dis[v.fi][i]);

		DP (v.fi);

	}

}

int main() {

	rd (n);

	rep (i, 2, n) {

		rdd (x, y);

		edge[x].pb (mp (i, y) );

	}

	dfs (1);

	DP (1);

	rep (i, 1, n) printf ("%d\n", ans[i]);

}

  

              

 

你可能感兴趣的:(NetWork)