标签:
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3749 Accepted Submission(s): 1892
HDU 2196:
题目意思:
求一棵树中的任意一个点到树中其他的节点的最长距离;
解题思路:
两次dp,第一次dp的时候求出以点i为根的子树中i到其他节点的最长距离,状态转移方程为:
dp[i]=max(dp[son]+w[i][son],dp[i]);
注:在第一次运算的时候,需要把最大值和次大值都记录下来;
第二次dp的时候算从i节点的父亲节点过来的最大值,如果i节点的父亲节点的最大值是从i节点进行状态转移转化过去的,则需要用此时的最大值与父亲节点的次大值加上边权值与原来的最大值比较;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<vector> 7 using namespace std; 8 const int maxn=10007; 9 int dp[maxn][3]; 10 struct node 11 { 12 int to,cost; 13 }; 14 vector<node> G[maxn]; 15 16 int n; 17 void init() 18 { 19 memset(dp,0,sizeof(dp)); 20 for(int i=0;i<maxn;i++) 21 G[i].clear(); 22 } 23 void slove1(int point,int father) 24 { 25 int big=0,bigger=0; 26 for(int i=0;i<G[point].size();i++) 27 { 28 int v=G[point][i].to; 29 if(v==father) continue; 30 slove1(v,point); 31 if(dp[v][0]+G[point][i].cost>big) 32 { 33 bigger=big; 34 big=dp[v][0]+G[point][i].cost; 35 } 36 else if(dp[v][0]+G[point][i].cost>bigger) bigger=dp[v][0]+G[point][i].cost; 37 } 38 dp[point][0]=big; 39 dp[point][1]=bigger; 40 } 41 void slove2(int point,int father) 42 { 43 int t; 44 for(int i=0;i<G[point].size();i++) 45 { 46 int v=G[point][i].to; 47 if(v==father) continue; 48 if(dp[point][0]==dp[v][0]+G[point][i].cost) t=dp[point][1]; 49 else t=dp[point][0]; 50 dp[v][2]=max(dp[point][2],t)+G[point][i].cost; 51 slove2(v,point); 52 } 53 } 54 int main() 55 { 56 // freopen("in.txt","r",stdin); 57 int a,b; 58 while(~scanf("%d",&n)){ 59 init();node n1; 60 for(int i=2;i<=n;i++) 61 { 62 scanf("%d %d",&a,&b); 63 n1.to=a;n1.cost=b; 64 G[i].push_back(n1); 65 n1.to=i; 66 G[a].push_back(n1); 67 } 68 slove1(1,-1); 69 dp[1][2]=0; 70 slove2(1,-1); 71 for(int i=1;i<=n;i++) 72 printf("%d\n",max(dp[i][2],dp[i][0])); 73 } 74 return 0; 75 }
标签:
原文地址:http://www.cnblogs.com/codeyuan/p/4319451.html