http://acm.hdu.edu.cn/showproblem.php?pid=2196
引用下别人的:
题意:给定一棵树,求每一个节点所能到达的最长路径的长度
分析:以编号的i的节点为例(非根节点),最长的路径长度只有俩种可能,1)子树中存在最长路径;2)通过父节点的路径中存在最长路径
所以,只有分别求出每一节点对应的那俩种路径取大最大值即可,当然,根节点只存在第一种可能
上面也给出了思路,有个要注意的地方是:
通过父亲结点找的最长路径不能经过这个结点本身。
这就要求父节点保存两个最值(最大和次大)
Realize:
先建图,这里用邻接表存储较好。
DP:
f[i]代表的是向下的最长路径
g[i]向下的次长路径
h[i]向上的最长路径
分两次DP
f[i]/g[i] = max{ f[child] } + w;
h[i] = max{h[parent], f[parent]/g[parent]} + w;
顺便学习了下STL里的vector的用法,有了STL,生活变得更简单~~~~
#include <cstdio> #include <iostream> #include <fstream> #include <cstring> #include <vector> using namespace std; #define MAX(a,b) ((a)>(b)?(a):(b)) struct edge { int ev,w; edge(){} edge(int a,int b):ev(a),w(b){} }; vector <edge> elist[10009]; int g[10009],f[10009],h[10009]; void DFS1(int fv) { int size = elist[fv].size(); if (!size) { f[fv] = g[fv] = 0; return; } int ev,w; for (int i = 0;i < size;i++) { ev = elist[fv][i].ev; w = elist[fv][i].w; DFS1(ev); if (f[ev] + w >= f[fv]) { g[fv] = f[fv]; f[fv] = f[ev] + w; //? } else { if (f[ev] + w > g[fv]) g[fv] = f[ev] + w; } } } void DFS2(int fv) { int size = elist[fv].size(); if (!size) { return; } int ev,w; for (int i = 0;i < size;i++) { ev = elist[fv][i].ev; w = elist[fv][i].w; if (f[ev] + w != f[fv]) { h[ev] = MAX(h[fv],f[fv]) + w;//h[i] = MAX(h[fv],f[fv]) + w; } else { h[ev] = MAX(h[fv],g[fv]) + w; } DFS2(ev); } } int main() { freopen("test.txt","r",stdin); int N; while(~scanf("%d",&N)) { for (int i = 1;i <= N;i++) elist[i].clear(); int fv,w; for (int i = 2;i <= N;i++) { scanf("%d%d",&fv,&w); elist[fv].push_back(edge(i,w)); } memset(f,0,sizeof(f)); memset(g,0,sizeof(g)); DFS1(1); DFS2(1); for (int i = 1;i <= N;i++) { //cout<<f[i]<<" "<<h[i]<<endl; printf("%d\n",MAX(f[i],h[i])); } } return 0; }