標籤:
題目大意:
每台新電腦都與某一台原電腦相連有一個長度,求每台電腦相距其最遠的電腦的距離
這裡因為第一台電腦是最初的,所以可以將第一台電腦作為樹根,其他電腦分布就可以形成一棵樹
這裡距離有兩種,一種是往樹底找,一種是往父節點方向走
第一次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\n" , maxn[i][0] , maxn[i][1] , maxn[i][2]);89 */90 for(int i=1 ; i<=n ; i++)91 printf("%d\n" , max(maxn[i][0] , maxn[i][2]));92 }93 return 0;94 }
HDU 2196 Computer 樹形DP