HDU 3534 Tree (树形DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3534
题意:给出一颗树(n个顶点,n-1条边)
求最长的路径,以及最长路径的条数。
路径无非就是连接两个点直接的路。
因为是一颗树,所以连接两个点肯定是唯一的路径。
其实就是求两点间距离的最大值,以及这个最大值有多少个。
很裸的树形DP;
首先统计出结点到叶子结点的最长距离和次长距离。
然后找寻经过这个点的,在这个为根结点的子树中的最长路径个数目。
代码:
#include <string.h> #include <iostream> #include <algorithm> #include <stdio.h> using namespace std; const int MAXN=100010; const int INF=0x3f3f3f3f; struct Node { int to,next,len; }edge[MAXN*2]; int head[MAXN]; int tol; int maxn[MAXN];//该节点往下到叶子结点的最大距离 int smaxn[MAXN];// 次大距离 int maxn_num[MAXN];//最大距离的个数 int smaxn_num[MAXN];//次大距离的个数 int path[MAXN];//该结点为根的子树中,包含该结点的最长路径长度 int num[MAXN];//最长路径的长度 void init() { tol=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[tol].to=v; edge[tol].len=w; edge[tol].next=head[u]; head[u]=tol++; edge[tol].to=u; edge[tol].len=w; edge[tol].next=head[v]; head[v]=tol++; } void dfs(int u,int pre) { maxn[u]=smaxn[u]=0; maxn_num[u]=smaxn_num[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; dfs(v,u); if(maxn[v]+edge[i].len>maxn[u]) { smaxn[u]=maxn[u]; smaxn_num[u]=maxn_num[u]; maxn[u]=maxn[v]+edge[i].len; maxn_num[u]=maxn_num[v]; } else if(maxn[v]+edge[i].len==maxn[u]) { maxn_num[u]+=maxn_num[v]; } else if(maxn[v]+edge[i].len>smaxn[u]) { smaxn[u]=maxn[v]+edge[i].len; smaxn_num[u]=maxn_num[v]; } else if(maxn[v]+edge[i].len==smaxn[u]) { smaxn_num[u]+=maxn_num[v]; } } if(maxn_num[u]==0)//叶子结点 { maxn[u]=smaxn[u]=0; maxn_num[u]=smaxn_num[u]=1; path[u]=0; num[u]=1; return; } int c1=0,c2=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; if(maxn[u]==maxn[v]+edge[i].len)c1++; else if(smaxn[u]==maxn[v]+edge[i].len)c2++; } path[u]=0; num[u]=0; if(c1>=2)//最长+最长 { int tmp=0; path[u]=maxn[u]*2; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; if(maxn[u]==maxn[v]+edge[i].len) { num[u]+=tmp*maxn_num[v]; tmp+=maxn_num[v]; } } } else if(c1>=1 && c2>=1)//最长+次长 { path[u]=maxn[u]+smaxn[u]; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; if(maxn[u]==maxn[v]+edge[i].len) { num[u]+=maxn_num[v]*smaxn_num[u]; } } } else//最长 { path[u]=maxn[u]; num[u]=maxn_num[u]; } } int main() { int n; while(scanf("%d",&n)==1) { int u,v,w; init(); for(int i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); } dfs(1,-1); int ans1=0,ans2=0; for(int i=1;i<=n;i++) { if(path[i]>ans1) { ans1=path[i]; ans2=num[i]; } else if(path[i]==ans1) ans2+=num[i]; } printf("%d %d\n",ans1,ans2); } return 0; }
人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想