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
", ans[i]);
}

  

              

原文地址:https://www.cnblogs.com/keam37/p/3844966.html