一开始总觉得是dfs序之类的问题,子树中的数量很好解决,一直在思考如何往上求数量。很久后才注意到边带权,然后只好放弃dfs序,只能考虑树形DP了。然后就是经典的求树的直径的改造。然后写搓了(大概就是第一遍dfs的时候维护的量不够多,所以在第二次dfs时就得用更多的运算量去弥补,即没有用更多的空间去换时间,所以超时了,以前这么写都能过啊,这次就不行了,更重要的是自己写得很不熟练,很多细节都搞错了,WA了好几发)。
以后自己一定要多看几遍题目,想一会,看一会,这样可以保证自己对题目有深刻的印象,防止自己理解有偏差或者想着想着就忘记了题目的限制条件。最后经典题目一定要做熟练,否则到了战场上还要再复习,还要一点一点磨,像什么样。
解题思路,就是经典树形DP——求树的直径的略加改编。
第一遍dfs求所有节点所在子树的(最大深度,对应的点的个数)和(次大深度,对应的点的个数)。
然后第二遍dfs求所有节点往上走的(最大长度,对应的点的个数)。
输出时循环+讨论一下即可。
搓代码
#include<bits/stdc++.h>
#define maxn 100010
using namespace std;
int N;
vector<int>G[maxn];
vector<int>W[maxn];
int d1[maxn],cd1[maxn],d2[maxn],cd2[maxn],df[maxn];
int up[maxn],cup[maxn];
int d[maxn],cd[maxn];
void dfs1(int u,int f)
{
d1[u]=d2[u]=cd1[u]=cd2[u]=-1;
for(unsigned int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==f)
{
df[u]=W[u][i];
continue;
}
dfs1(v,u);
int D=W[u][i]+d1[v];
if(D>d1[u])
{
d2[u]=d1[u];
cd2[u]=cd1[u];
d1[u]=D;
cd1[u]=cd1[v];
}
else if(D==d1[u]) cd1[u]+=cd1[v];
else if(D>d2[u])
{
d2[u]=D;
cd2[u]=cd1[v];
}
else if(D==d2[u]) cd2[u]+=cd1[v];
}
if(d1[u]==-1)
{
d1[u]=0;
cd1[u]=1;
}
}
void dfs2(int u,int f)
{
up[u]=up[f]+df[u];
cup[u]=cup[f];
if(!(d1[u]+df[u]==d1[f]&&cd1[f]==cd1[u]))
{
int D=d1[f]+df[u];
if(D>up[u])
{
up[u]=D;
cup[u]=cd1[f];
if(d1[u]+df[u]==d1[f]) cup[u]-=cd1[u];
}
else if(D==up[u])
{
cup[u]+=cd1[f];
if(d1[u]+df[u]==d1[f]) cup[u]-=cd1[u];
}
}
else if(cd2[f]!=-1)
{
if(d1[f]==d1[u]+df[u])
{
int D=d2[f]+df[u];
if(D>up[u])
{
up[u]=D;
cup[u]=cd2[f];
}
else if(D==up[u]) cup[u]+=cd2[f];
}
else
{
int D=d1[f]+df[u];
if(D>up[u])
{
up[u]=D;
cup[u]=cd1[f];
if(d1[u]+df[u]==d1[f]) cup[u]-=cd1[u];
}
else if(D==up[u])
{
cup[u]+=cd1[f];
if(d1[u]+df[u]==d1[f]) cup[u]-=cd1[u];
}
}
}
if(d1[u]==up[u])
{
d[u]=d1[u];
cd[u]=cd1[u]+cup[u];
}
else if(d1[u]>up[u])
{
d[u]=d1[u];
cd[u]=cd1[u];
}
else
{
d[u]=up[u];
cd[u]=cup[u];
}
for(unsigned int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(v==f) continue;
dfs2(v,u);
}
}
int kase;
int main()
{
up[0]=0;
cup[0]=1;
G[0].push_back(1);
W[0].push_back(0);
while(~scanf("%d",&N))
{
for(int i=1;i<=N;i++)
{
G[i].clear();
W[i].clear();
}
int u,v,w;
for(int i=1;i<N;i++)
{
scanf("%d %d %d",&u,&v,&w);
G[u].push_back(v);
W[u].push_back(w);
G[v].push_back(u);
W[v].push_back(w);
}
dfs1(1,0);
dfs2(1,0);
printf("Case #%d:",++kase);
for(int i=1;i<=N;i++)
printf(" %d",cd[i]);
puts("");
}
return 0;
}