题目大意:
每台新电脑都与某一台原电脑相连有一个长度,求每台电脑相距其最远的电脑的距离
这里因为第一台电脑是最初的,所以可以将第一台电脑作为树根,其他电脑分布就可以形成一棵树
这里距离有两种,一种是往树底找,一种是往父节点方向走
第一次dfs记录下每个节点往子节点方向找到其树底的最长距离,第二次dfs记录每个节点如果一开始往父节点方向走所能得到的最大距离
最后判断两者中得到一个最大值就行了
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 6 const int N = 10005; 7 8 int first[N] , maxn[N][4] , k , vis[N]; 9 /* 10 maxn[i][0] 表示i往下到其树底的最长距离, 11 maxn[i][1]表示到树底的次长距离, 12 maxn[i][2]表示i节点往上寻找到的最长距离 13 最后只要比较判断往上找还是往下找能得到的最大距离即可 14 */ 15 struct Edge{ 16 int y , next , d; 17 }e[N<<1]; 18 19 void add_edge(int x , int y , int d) 20 { 21 e[k].y = y , e[k].d = d , e[k].next = first[x]; 22 first[x] = k++; 23 } 24 25 void my_swap(int &x , int &y) 26 { 27 int temp = x; 28 x = y , y = temp; 29 } 30 31 void dfs1(int u) 32 { 33 vis[u] = 1; 34 for(int i = first[u] ; i!=-1 ; i=e[i].next){ 35 int v = e[i].y; 36 if(!vis[v]){ 37 dfs1(v); 38 //更新次长和最长值,自底向上更新,所以写在dfs后面进行回溯 39 if(maxn[u][1] < maxn[v][0] + e[i].d){ 40 maxn[u][1] = maxn[v][0] + e[i].d; 41 if(maxn[u][0] < maxn[u][1]) 42 my_swap(maxn[u][0] , maxn[u][1]); 43 } 44 } 45 } 46 } 47 48 void dfs2(int u) 49 { 50 vis[u] = 1; 51 for(int i= first[u] ; i!=-1 ; i=e[i].next){ 52 int v = e[i].y; 53 if(!vis[v]){ 54 //自顶向下更新,所以写在dfs前面 55 //判断是否最大值落于当前分支 56 int tmp; 57 if(maxn[u][0] - maxn[v][0] == e[i].d) 58 tmp = maxn[u][1]; 59 else tmp = maxn[u][0]; 60 maxn[v][2] = max(maxn[u][2] , tmp) + e[i].d; 61 dfs2(v); 62 } 63 } 64 } 65 66 int main() 67 { 68 // freopen("a.in" , "r" , stdin); 69 int n , d , a; 70 while(scanf("%d" , &n) == 1) 71 { 72 k = 0; 73 memset(first , -1 , sizeof(first)); 74 for(int i=2 ; i<=n ; i++){ 75 scanf("%d%d" , &a , &d); 76 add_edge(a , i , d); 77 add_edge(i , a , d); 78 } 79 80 memset(maxn , 0 , sizeof(maxn)); 81 memset(vis , 0 , sizeof(vis)); 82 dfs1(1); 83 84 memset(vis , 0 , sizeof(vis)); 85 dfs2(1); 86 /* 87 for(int i=1 ; i<=n ; i++) 88 printf("%d %d %d " , maxn[i][0] , maxn[i][1] , maxn[i][2]); 89 */ 90 for(int i=1 ; i<=n ; i++) 91 printf("%d " , max(maxn[i][0] , maxn[i][2])); 92 } 93 return 0; 94 }