题意:统计一棵带权树上两点之间的最长距离以及最长距离的数目
链接:点我
首先统计出结点到叶子结点的最长距离和次长距离。
然后找寻经过这个点的,在这个为根结点的子树中的最长路径个数目。
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 ",ans1,ans2); 146 } 147 return 0; 148 }