hdu 3534 树形dp ***

题意:统计一棵带权树上两点之间的最长距离以及最长距离的数目

链接:点我

首先统计出结点到叶子结点的最长距离和次长距离。

然后找寻经过这个点的,在这个为根结点的子树中的最长路径个数目。

  1 #include <string.h>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <stdio.h>
  5 using namespace std;
  6 const int MAXN=100010;
  7 const int INF=0x3f3f3f3f;
  8 struct Node
  9 {
 10     int to,next,len;
 11 }edge[MAXN*2];
 12 int head[MAXN];
 13 int tol;
 14 int maxn[MAXN];//该节点往下到叶子结点的最大距离
 15 int smaxn[MAXN];// 次大距离
 16 int maxn_num[MAXN];//最大距离的个数
 17 int smaxn_num[MAXN];//次大距离的个数
 18 int path[MAXN];//该结点为根的子树中,包含该结点的最长路径长度
 19 int num[MAXN];//最长路径的长度
 20
 21 void init()
 22 {
 23     tol=0;
 24     memset(head,-1,sizeof(head));
 25 }
 26 void add(int u,int v,int w)
 27 {
 28     edge[tol].to=v;
 29     edge[tol].len=w;
 30     edge[tol].next=head[u];
 31     head[u]=tol++;
 32     edge[tol].to=u;
 33     edge[tol].len=w;
 34     edge[tol].next=head[v];
 35     head[v]=tol++;
 36 }
 37
 38 void dfs(int u,int pre)
 39 {
 40     maxn[u]=smaxn[u]=0;
 41     maxn_num[u]=smaxn_num[u]=0;
 42     for(int i=head[u];i!=-1;i=edge[i].next)
 43     {
 44         int v=edge[i].to;
 45         if(v==pre)continue;
 46         dfs(v,u);
 47         if(maxn[v]+edge[i].len>maxn[u])
 48         {
 49             smaxn[u]=maxn[u];
 50             smaxn_num[u]=maxn_num[u];
 51             maxn[u]=maxn[v]+edge[i].len;
 52             maxn_num[u]=maxn_num[v];
 53         }
 54         else if(maxn[v]+edge[i].len==maxn[u])
 55         {
 56             maxn_num[u]+=maxn_num[v];
 57         }
 58         else if(maxn[v]+edge[i].len>smaxn[u])
 59         {
 60             smaxn[u]=maxn[v]+edge[i].len;
 61             smaxn_num[u]=maxn_num[v];
 62         }
 63         else if(maxn[v]+edge[i].len==smaxn[u])
 64         {
 65             smaxn_num[u]+=maxn_num[v];
 66         }
 67     }
 68     if(maxn_num[u]==0)//叶子结点
 69     {
 70         maxn[u]=smaxn[u]=0;
 71         maxn_num[u]=smaxn_num[u]=1;
 72         path[u]=0;
 73         num[u]=1;
 74         return;
 75     }
 76     //到这里已经统计出了u节点到叶子的最长和次长
 77     int c1=0,c2=0;
 78     for(int i=head[u];i!=-1;i=edge[i].next)
 79     {
 80         int v=edge[i].to;
 81         if(v==pre)continue;
 82         if(maxn[u]==maxn[v]+edge[i].len)c1++;
 83         else if(smaxn[u]==maxn[v]+edge[i].len)c2++;
 84     }
 85     path[u]=0;
 86     num[u]=0;
 87     if(c1>=2)//最长+最长
 88     {
 89         int tmp=0;
 90         path[u]=maxn[u]*2;
 91         for(int i=head[u];i!=-1;i=edge[i].next)
 92         {
 93             int v=edge[i].to;
 94             if(v==pre)continue;
 95             if(maxn[u]==maxn[v]+edge[i].len)
 96             {
 97                 num[u]+=tmp*maxn_num[v];
 98                 tmp+=maxn_num[v];
 99             }
100         }
101     }
102     else if(c1>=1 && c2>=1)//最长+次长
103     {
104         path[u]=maxn[u]+smaxn[u];
105         for(int i=head[u];i!=-1;i=edge[i].next)
106         {
107             int v=edge[i].to;
108             if(v==pre)continue;
109             if(maxn[u]==maxn[v]+edge[i].len)
110             {
111                 num[u]+=maxn_num[v]*smaxn_num[u];
112             }
113         }
114     }
115     else//最长
116     {
117         path[u]=maxn[u];
118         num[u]=maxn_num[u];
119     }
120 }
121 int main()
122 {
123     int n;
124     while(scanf("%d",&n)==1)
125     {
126         int u,v,w;
127         init();
128         for(int i=1;i<n;i++)
129         {
130             scanf("%d%d%d",&u,&v,&w);
131             add(u,v,w);
132         }
133         dfs(1,-1);
134         int ans1=0,ans2=0;
135         for(int i=1;i<=n;i++)
136         {
137             if(path[i]>ans1)
138             {
139                 ans1=path[i];
140                 ans2=num[i];
141             }
142             else if(path[i]==ans1)
143                 ans2+=num[i];
144         }
145         printf("%d %d\n",ans1,ans2);
146     }
147     return 0;
148 }
时间: 2024-10-11 15:30:35

hdu 3534 树形dp ***的相关文章

hdu 4123 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses,

hdu 1250 树形DP

Anniversary party Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-27) Description There is going to be a party to celebrate the 80-th Anniversary of the Ural St

hdu 4276(树形dp)

题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏. 思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权.dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏. dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]); 被G++卡了好长时间,换成c++就过了. 代码如下: 1 #include <stdio.h> 2 #include <string.h

hdu 5148 树形dp+分组背包问题

http://acm.hdu.edu.cn/showproblem.php?pid=5148 Problem Description Long long ago,there is a knight called JayYe.He lives in a small country.This country is made up of n cities connected by n-1 roads(that means it's a tree).The king wants to reward Ja

HDU 1520 树形dp裸题

1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #include<cstdio> #define max(a,b) a>b?a:b using nam

hdu 3586 树形dp+二分

题目大意:给定n个敌方据点,1为司令部,其他点各有一条边相连构成一棵 树,每条边都有一个权值cost表示破坏这条边的费用,叶子节点为前线.现要切断前线和司令部的联系,每次切断边的费用不能超过上限limit,问切断所 有前线与司令部联系所花费的总费用少于m时的最小limit.1<=n<=1000,1<=m<=100万 题目要问的是最小的最大限制,必然二分答案 然后对于每一个值,树形DP判定是否可行 dp[i]表示要切断以i为根的其它所有子树的最小代价. 其中设定叶子结点的代价为无穷大

HDU 1561 树形DP入门

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6011    Accepted Submission(s): 3555 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物

hdu 1561 树形dp

又一道树形dp,发现其实树形dp长得都挺像的. 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = -9999999; 7 const int N = 201; 8 int dp[N][N]; 9 int head[N]; 10 int value[N]; 11 int n, m, e; 12 13 void i

hdu 1011 树形dp+背包

题意:有n个房间结构可看成一棵树,有m个士兵,从1号房间开始让士兵向相邻的房间出发,每个房间有一定的敌人,每个士兵可以对抗20个敌人,士兵在某个房间对抗敌人使无法走开,同时有一个价值,问你花费这m个士兵可以得到的最大价值是多少 分析:树形dp,对于点u,dp[u][j]表示以u为根的树消耗j个士兵得到的最大值,dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son][k]+val[u]) 注意是无向图,vis位置不能随便放,且注意dp不能直接+val,因为这样根节点就加不