hdu2196Computer 树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2196
思路:
一看就是一道树形DP的题目,对于一个节点来说,到它的最远距离的路径可能来于子树,也可能来源于经过父亲节点的路径,所以我们两次DFS即可。
第一次DFS自底向上(从叶节点开始),依次求出每个节点的在其子树上的最大距离和次大距离
第二次DFS自顶向下(从根节点开始),通过比较经过父亲节点的路径的最大距离和来源于子树的最大距离比较然后更新最大距离
至于为什么要保存次大距离呢??因为经过父亲节点的最大距离可能刚好经过当前的孩子节点,那么我们就只能通过当前孩子到父亲节点的距离加上经过父亲节点的路径次大值和当前节点的位于其子树的路径的最大距离的比较来更新最大距离咯。
虽然思路还是比较清晰的,自己实现起来还是比较难的。。。。
代码如下:
1 #include<cstdlib> 2 #include<cstring> 3 #include<cstdio> 4 #include<iostream> 5 using namespace std; 6 #define MAX 10010 7 class node 8 { 9 public: 10 int to; 11 int w; 12 int next; 13 14 }; 15 node edge[2*MAX]; 16 int head[MAX]; 17 int tol; 18 int maxn[MAX]; 19 int smaxn[MAX]; 20 int m_id[MAX]; 21 int sm_id[MAX]; 22 int vis[MAX]; 23 void init() 24 { 25 memset(head,-1,sizeof(head)); 26 memset(maxn,0,sizeof(maxn)); 27 memset(smaxn,0,sizeof(smaxn)); 28 memset(vis,0,sizeof(vis)); 29 tol=0; 30 } 31 void Build_Tree(int u,int v,int w) 32 { 33 edge[tol].to=v; 34 edge[tol].w=w; 35 edge[tol].next=head[u]; 36 head[u]=tol++; 37 } 38 void dfs1(int root,int parent) 39 { 40 vis[root]=1; 41 for(int i=head[root];i!=-1;i=edge[i].next) 42 { 43 if(vis[edge[i].to]) continue; 44 int son=edge[i].to; 45 dfs1(son,root); 46 int len=edge[i].w; 47 if(smaxn[root]<maxn[son]+len) 48 { 49 smaxn[root]=maxn[son]+len; 50 sm_id[root]=son; 51 if(smaxn[root]>maxn[root]) 52 { 53 swap(smaxn[root],maxn[root]); 54 swap(sm_id[root],m_id[root]); 55 } 56 } 57 } 58 } 59 void dfs2(int root ,int parent) 60 { 61 for(int i=head[root];i!=-1;i=edge[i].next) 62 { 63 if(edge[i].to==parent) continue; 64 int son=edge[i].to; 65 if(m_id[root]==son) 66 { 67 if(edge[i].w+smaxn[root]>smaxn[son]) 68 { 69 smaxn[son]=edge[i].w+smaxn[root]; 70 sm_id[son]=root; 71 if(smaxn[son]>maxn[son]) 72 { 73 swap(smaxn[son],maxn[son]); 74 swap(sm_id[son],m_id[son]); 75 } 76 } 77 } 78 else 79 { 80 if(edge[i].w+maxn[root]>smaxn[son]) 81 { 82 smaxn[son]=edge[i].w+maxn[root]; 83 sm_id[son]=root; 84 if(smaxn[son]>maxn[son]) 85 { 86 swap(smaxn[son],maxn[son]); 87 swap(m_id[son],sm_id[son]); 88 } 89 } 90 } 91 dfs2(son,root); 92 } 93 94 } 95 int n; 96 int main() 97 { 98 while(scanf("%d",&n)!=EOF) 99 { 100 init(); 101 for(int i=2;i<=n;i++) 102 { 103 int u,w; 104 scanf("%d%d",&u,&w); 105 Build_Tree(i,u,w); 106 Build_Tree(u,i,w); 107 } 108 dfs1(1,-1); 109 dfs2(1,-1); 110 for(int i=1;i<=n;i++) 111 cout<<maxn[i]<<endl; 112 113 } 114 return 0; 115 }